From 41b8f76adc1dd093985d544c15381a5d62066e7f Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Fri, 30 May 2008 12:00:21 +0000 Subject: * src/Makefile.am: * src/db-artwork-parser.c: * src/db-artwork-writer.c: * src/db-image-parser.c: * src/db-image-parser.h: * src/itdb.h: * src/itdb_artwork.c: * src/itdb_device.h: * src/itdb_photoalbum.c: * src/itdb_track.c: * src/ithumb-writer.c: * tests/test-covers.c: * tests/test-photos.c: rework Itdb_Thumb type. Now it's split into different subtypes depending on what it represents (GdkPixbuf, thumbnail read from the ipod, ...). Itdb_Artwork now contains only a pointer to a single Itdb_Thumb (it used to contain a GList * of Itdb_Thumb) since the only time when the list is useful is for thumbs read from the ipod. Using a list for the other types of thumbnails created some complications when trying to set art on an Itdb_Track that wasn't attached to an Itdb_iTunesDB. git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1991 f01d2545-417e-4e96-918e-98f8d0dbbcb6 --- ChangeLog | 23 +++ src/Makefile.am | 2 + src/db-artwork-parser.c | 21 +- src/db-artwork-writer.c | 124 +++-------- src/db-image-parser.c | 72 ++----- src/db-image-parser.h | 11 +- src/itdb.h | 75 ++----- src/itdb_artwork.c | 531 +++++++++--------------------------------------- src/itdb_device.h | 1 - src/itdb_photoalbum.c | 48 ++--- src/itdb_track.c | 121 +++++------ src/ithumb-writer.c | 298 ++++++++++++++++----------- tests/test-covers.c | 70 ++++--- tests/test-photos.c | 33 ++- 14 files changed, 524 insertions(+), 906 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b1dcaf..bab20b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-05-30 Christophe Fergeau + + * src/Makefile.am: + * src/db-artwork-parser.c: + * src/db-artwork-writer.c: + * src/db-image-parser.c: + * src/db-image-parser.h: + * src/itdb.h: + * src/itdb_artwork.c: + * src/itdb_device.h: + * src/itdb_photoalbum.c: + * src/itdb_track.c: + * src/ithumb-writer.c: + * tests/test-covers.c: + * tests/test-photos.c: rework Itdb_Thumb type. Now it's split into + different subtypes depending on what it represents (GdkPixbuf, + thumbnail read from the ipod, ...). Itdb_Artwork now contains only a + pointer to a single Itdb_Thumb (it used to contain a GList * of + Itdb_Thumb) since the only time when the list is useful is for thumbs + read from the ipod. Using a list for the other types of thumbnails + created some complications when trying to set art on an Itdb_Track that + wasn't attached to an Itdb_iTunesDB. + 2008-05-29 Christophe Fergeau * src/itunesdb.c: diff --git a/src/Makefile.am b/src/Makefile.am index 89851f9..49260f5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,7 @@ libgpod_la_SOURCES = \ itdb_plist.c \ itdb_sha1.c \ itdb_sysinfo_extended_parser.c \ + itdb_thumb.c \ itdb_track.c \ ithumb-writer.c \ pixmaps.c \ @@ -37,6 +38,7 @@ noinst_HEADERS = \ itdb_private.h \ itdb_sha1.h \ itdb_sysinfo_extended_parser.h \ + itdb_thumb.h \ pixmaps.h \ sha1.h diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c index 07b21a9..e993eee 100644 --- a/src/db-artwork-parser.c +++ b/src/db-artwork-parser.c @@ -163,7 +163,7 @@ parse_mhod_string (DBParseContext *ctx, GError *error) static int parse_mhod_3 (DBParseContext *ctx, - Itdb_Thumb *thumb, GError *error) + Itdb_Thumb_Ipod_Item *thumb, GError *error) { struct ParsedMhodString *mhod; mhod = parse_mhod_string (ctx, error); @@ -182,11 +182,11 @@ parse_mhod_3 (DBParseContext *ctx, } static int -parse_photo_mhni (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error) +parse_photo_mhni (DBParseContext *ctx, Itdb_Thumb_Ipod *thumbs, GError *error) { MhniHeader *mhni; DBParseContext *mhod_ctx; - Itdb_Thumb *thumb; + Itdb_Thumb_Ipod_Item *thumb; mhni = db_parse_context_get_m_header (ctx, MhniHeader, "mhni"); if (mhni == NULL) { @@ -199,8 +199,8 @@ parse_photo_mhni (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error) if (thumb == NULL) { return 0; } - - artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); + + itdb_thumb_ipod_add (thumbs, thumb); mhod_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); if (mhod_ctx == NULL) { @@ -213,7 +213,7 @@ parse_photo_mhni (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error) } static int -parse_photo_mhod (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error) +parse_photo_mhod (DBParseContext *ctx, Itdb_Thumb_Ipod *thumbs, GError *error) { ArtworkDB_MhodHeader *mhod; DBParseContext *mhni_ctx; @@ -235,7 +235,7 @@ parse_photo_mhod (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error) if (mhni_ctx == NULL) { return -1; } - parse_photo_mhni (mhni_ctx, artwork, NULL); + parse_photo_mhni (mhni_ctx, thumbs, NULL); g_free (mhni_ctx); } @@ -253,7 +253,8 @@ parse_mhii (DBParseContext *ctx, GError *error) Itdb_PhotoDB *photodb; guint64 mactime; Itdb_Device *device = db_get_device (ctx->db); - + Itdb_Thumb_Ipod *thumbs; + mhii = db_parse_context_get_m_header (ctx, MhiiHeader, "mhii"); if (mhii == NULL) { @@ -275,12 +276,14 @@ parse_mhii (DBParseContext *ctx, GError *error) artwork->artwork_size = get_gint32 (mhii->orig_img_size, ctx->byte_order); artwork->dbid = get_gint64 (mhii->song_id, ctx->byte_order); + thumbs = (Itdb_Thumb_Ipod *)itdb_thumb_ipod_new (); + artwork->thumbnail = (Itdb_Thumb *)thumbs; 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); + parse_photo_mhod (mhod_ctx, thumbs, NULL); num_children--; cur_offset += mhod_ctx->total_len; g_free (mhod_ctx); diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c index b2a0ab4..a24b0fd 100644 --- a/src/db-artwork-writer.c +++ b/src/db-artwork-writer.c @@ -357,14 +357,15 @@ write_mhod_type_3 (gchar *string, iPodBuffer *buffer) } static int -write_mhni (Itdb_DB *db, Itdb_Thumb *thumb, int format_id, iPodBuffer *buffer) +write_mhni (Itdb_DB *db, Itdb_Thumb_Ipod_Item *item, iPodBuffer *buffer) { MhniHeader *mhni; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; + const Itdb_ArtworkFormat *format; - if (thumb == NULL) { + if (item == NULL) { return -1; } @@ -377,21 +378,22 @@ write_mhni (Itdb_DB *db, Itdb_Thumb *thumb, int format_id, iPodBuffer *buffer) buffer->byte_order); mhni->total_len = get_gint32 (total_bytes, buffer->byte_order); - mhni->format_id = get_gint32 (format_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->vertical_padding = get_gint16 (thumb->vertical_padding, + format = item->format; + mhni->format_id = get_gint32 (format->format_id, buffer->byte_order); + mhni->image_width = get_gint16 (item->width, buffer->byte_order); + mhni->image_height = get_gint16 (item->height, buffer->byte_order); + mhni->image_size = get_gint32 (item->size, buffer->byte_order); + mhni->ithmb_offset = get_gint32 (item->offset, buffer->byte_order); + mhni->vertical_padding = get_gint16 (item->vertical_padding, buffer->byte_order); - mhni->horizontal_padding = get_gint16 (thumb->horizontal_padding, + mhni->horizontal_padding = get_gint16 (item->horizontal_padding, 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->filename, sub_buffer); + bytes_written = write_mhod_type_3 (item->filename, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; @@ -410,7 +412,7 @@ write_mhni (Itdb_DB *db, Itdb_Thumb *thumb, int format_id, iPodBuffer *buffer) } static int -write_mhod (Itdb_DB *db, Itdb_Thumb *thumb, int format_id, iPodBuffer *buffer) +write_mhod (Itdb_DB *db, Itdb_Thumb_Ipod_Item *thumb, iPodBuffer *buffer) { ArtworkDB_MhodHeader *mhod; unsigned int total_bytes; @@ -434,7 +436,7 @@ write_mhod (Itdb_DB *db, Itdb_Thumb *thumb, int format_id, iPodBuffer *buffer) if (sub_buffer == NULL) { return -1; } - bytes_written = write_mhni (db, thumb, format_id, sub_buffer); + bytes_written = write_mhni (db, thumb, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; @@ -455,7 +457,7 @@ write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer) unsigned int total_bytes; int bytes_written; int num_children; - GList *it = NULL; + const GList *it = NULL; Itdb_Track *song; Itdb_Artwork *artwork; guint64 mactime; @@ -493,16 +495,20 @@ write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer) mhii->orig_img_size = get_gint32 (artwork->artwork_size, buffer->byte_order); num_children = 0; - for (it=artwork->thumbnails; it!=NULL; it=it->next) + /* Before trying to write the artwork or photo database, the ithmb + * files have been written, which will have converted all thumbnails + * attached to the tracks to ITDB_THUMB_TYPE_IPOD thumbnails. + */ + g_assert (artwork->thumbnail->data_type == ITDB_THUMB_TYPE_IPOD); + for (it=itdb_thumb_ipod_get_thumbs ((Itdb_Thumb_Ipod *)artwork->thumbnail); + it!=NULL; + it=it->next) { iPodBuffer *sub_buffer; - Itdb_Thumb *thumb; - const Itdb_ArtworkFormat *img_info; + Itdb_Thumb_Ipod_Item *thumb; - thumb = (Itdb_Thumb *)it->data; - img_info = itdb_get_artwork_info_from_type ( - db_get_device(db), thumb->type); - if (img_info == NULL) { + thumb = (Itdb_Thumb_Ipod_Item *)it->data; + if (thumb->format == NULL) { /* skip this thumb */ continue; } @@ -514,8 +520,7 @@ write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer) if (sub_buffer == NULL) { return -1; } - bytes_written = write_mhod (db, thumb, img_info->format_id, - sub_buffer); + bytes_written = write_mhod (db, thumb, sub_buffer); ipod_buffer_destroy (sub_buffer); if (bytes_written == -1) { return -1; @@ -564,7 +569,7 @@ write_mhli (Itdb_DB *db, iPodBuffer *buffer ) iPodBuffer *sub_buffer; if (buffer->db_type == DB_TYPE_ITUNES) { song = (Itdb_Track*)it->data; - if (!song->artwork->thumbnails || (song->artwork->id == 0)) { + if (!song->artwork->thumbnail || (song->artwork->id == 0)) { it = it->next; continue; } @@ -743,9 +748,10 @@ write_mhif (Itdb_DB *db, iPodBuffer *buffer, } G_GNUC_INTERNAL gboolean -itdb_thumb_type_is_valid_for_db (const ItdbThumbType thumb_type, DbType db_type) +itdb_thumb_type_is_valid_for_db (const Itdb_ArtworkFormat *format, + DbType db_type) { - switch (thumb_type) { + switch (format->type) { case ITDB_THUMB_COVER_SMALL: case ITDB_THUMB_COVER_LARGE: case ITDB_THUMB_COVER_XLARGE: @@ -791,7 +797,7 @@ write_mhlf (Itdb_DB *db, iPodBuffer *buffer) while (formats->type != -1) { iPodBuffer *sub_buffer; - if (!itdb_thumb_type_is_valid_for_db (formats->type, buffer->db_type)) { + if (!itdb_thumb_type_is_valid_for_db (formats, buffer->db_type)) { formats++; continue; } @@ -932,7 +938,7 @@ ipod_artwork_db_set_ids (Itdb_iTunesDB *db) if (max_id <= song->id) { max_id = song->id; } - if (song->artwork->thumbnails != NULL) { + if (song->artwork->thumbnail != NULL) { song->artwork->id = song->id; } } @@ -940,67 +946,6 @@ ipod_artwork_db_set_ids (Itdb_iTunesDB *db) return max_id; } - -static void -itdb_track_filter_thumbnails (Itdb_iTunesDB *itdb, Itdb_Track *track) -{ - const Itdb_ArtworkFormat *formats; - const Itdb_ArtworkFormat *format; - GList *it; - GList *supported_thumbs; - - if (track->artwork == NULL) { - return; - } - - if (track->artwork->thumbnails == NULL) { - return; - } - - if (itdb->device == NULL) { - itdb_artwork_free (track->artwork); - track->artwork = NULL; - return; - } - - formats = itdb_device_get_artwork_formats (itdb->device); - if (formats == NULL) { - itdb_artwork_remove_thumbnails (track->artwork); - return; - } - - supported_thumbs = NULL; - for (format = formats; format->type != -1; format++) { - for (it = track->artwork->thumbnails; it != NULL; it = it->next) { - Itdb_Thumb *thumb = (Itdb_Thumb *)it->data; - - if (thumb->type == format->type) { - supported_thumbs = g_list_prepend (supported_thumbs, it->data); - /* Remove element from the original list, there will - * be less work next time we iterate over the thumbnails - */ - track->artwork->thumbnails = g_list_remove_link (track->artwork->thumbnails, it); - break; - } - } - } - - g_list_free (track->artwork->thumbnails); - track->artwork->thumbnails = supported_thumbs; -} - -static void -itdb_filter_thumbnails (Itdb_iTunesDB *itdb) -{ - GList *it; - - for (it = itdb->tracks; it != NULL; it = it->next) { - itdb_track_filter_thumbnails (itdb, (Itdb_Track *)it->data); - } -} - - - int ipod_write_artwork_db (Itdb_iTunesDB *itdb) { @@ -1013,9 +958,6 @@ ipod_write_artwork_db (Itdb_iTunesDB *itdb) db.db_type = DB_TYPE_ITUNES; db.db.itdb = itdb; - - itdb_filter_thumbnails (itdb); - /* First, let's write the .ithmb files, this will create the * various thumbnails as well */ diff --git a/src/db-image-parser.c b/src/db-image-parser.c index dfc7d5d..8128e19 100644 --- a/src/db-image-parser.c +++ b/src/db-image-parser.c @@ -35,66 +35,51 @@ #include "db-image-parser.h" #include -static int -image_type_from_format_id (Itdb_Device *device, gint16 format_id) +static const Itdb_ArtworkFormat * +image_format_from_id (Itdb_Device *device, gint16 format_id) { const Itdb_ArtworkFormat *formats; if (device == NULL) { - return -1; + return NULL; } formats = itdb_device_get_artwork_formats (device); if (formats == NULL) { - return -1; + return NULL; } while (formats->type != -1) { if (formats->format_id == format_id) { - return formats->type; + return formats; } formats++; } - return -1; -} - - -G_GNUC_INTERNAL const Itdb_ArtworkFormat * -itdb_get_artwork_info_from_type (Itdb_Device *device, - ItdbThumbType image_type) -{ - const Itdb_ArtworkFormat *formats; - - if (device == NULL) { - return NULL; - } - - formats = itdb_device_get_artwork_formats (device); - if (formats == NULL) { - return NULL; - } - - while ((formats->type != -1) && (formats->type != image_type)) { - formats++; - } - - if (formats->type == -1) { - return NULL; - } - - return formats; + return NULL; } -G_GNUC_INTERNAL Itdb_Thumb * +G_GNUC_INTERNAL Itdb_Thumb_Ipod_Item * ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_DB *db) { - Itdb_Thumb *img; + Itdb_Thumb_Ipod_Item *img; + const Itdb_ArtworkFormat *format; gint16 format_id; Itdb_Device *device = NULL; - img = g_new0 (Itdb_Thumb, 1); + device = db_get_device (db); + g_return_val_if_fail (device, NULL); + + format_id = get_gint32_db (db, mhni->format_id); + format = image_format_from_id (device, format_id); + if (format == NULL) { + g_warning (_("Unexpected image type in mhni: %d, offset: %d\n"), + format_id, get_guint32_db (db, mhni->ithmb_offset)); + return NULL; + } + + img = itdb_thumb_new_item_from_ipod (format); if (img == NULL) { return NULL; } @@ -107,25 +92,10 @@ ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_DB *db) img->vertical_padding = get_gint16_db (db, mhni->vertical_padding); - device = db_get_device (db); - g_return_val_if_fail (device, NULL); - - format_id = get_gint32_db (db, mhni->format_id); - img->type = image_type_from_format_id (device, format_id); - #if DEBUG_ARTWORK printf ("format_id: %d, of: %6d sz: %6d, x: %3d, y: %3d, xpad: %3d, ypad: %3d\n", format_id, img->offset, img->size, img->width, img->height, img->horizontal_padding, img->vertical_padding); #endif - if (img->type == -1) - { - g_warning (_("Unexpected image type in mhni: size: %ux%u (%d), offset: %d\n"), - img->width, img->height, - format_id, img->offset); - g_free (img); - return NULL; - } - return img; } diff --git a/src/db-image-parser.h b/src/db-image-parser.h index a9a3862..c8fbbe4 100644 --- a/src/db-image-parser.h +++ b/src/db-image-parser.h @@ -29,6 +29,7 @@ #include "db-itunes-parser.h" #include "itdb_device.h" #include "itdb_private.h" +#include "itdb_thumb.h" #include "itdb.h" #define DEBUG_ARTWORK 0 @@ -77,16 +78,12 @@ #define BLUE_SHIFT_888 0 #define BLUE_MASK_888 (((1 << BLUE_BITS_888)-1) << BLUE_SHIFT_888) -G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni, - Itdb_DB *db); +G_GNUC_INTERNAL Itdb_Thumb_Ipod_Item *ipod_image_new_from_mhni (MhniHeader *mhni, + Itdb_DB *db); G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_DB *db); G_GNUC_INTERNAL gboolean -itdb_thumb_type_is_valid_for_db (const ItdbThumbType thumb_type, DbType db_type); - -G_GNUC_INTERNAL -const Itdb_ArtworkFormat *itdb_get_artwork_info_from_type ( - Itdb_Device *ipod, ItdbThumbType image_type); +itdb_thumb_type_is_valid_for_db (const Itdb_ArtworkFormat *format, DbType db_type); #endif diff --git a/src/itdb.h b/src/itdb.h index 90dd5d4..3ef593d 100644 --- a/src/itdb.h +++ b/src/itdb.h @@ -57,6 +57,7 @@ typedef gpointer (* ItdbUserDataDuplicateFunc) (gpointer userdata); typedef struct _Itdb_Device Itdb_Device; typedef struct _Itdb_IpodInfo Itdb_IpodInfo; typedef struct _Itdb_Artwork Itdb_Artwork; +typedef struct _Itdb_ArtworkFormat Itdb_ArtworkFormat; typedef struct _Itdb_Thumb Itdb_Thumb; typedef struct _Itdb_SPLPref Itdb_SPLPref; typedef struct _Itdb_SPLRule Itdb_SPLRule; @@ -494,51 +495,19 @@ typedef enum { ITDB_THUMB_CHAPTER_LARGE, /* classic -- not supported yet */ } ItdbThumbType; - -/* The Itdb_Thumb structure can represent two slightly different - thumbnails: - - a) 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 OR image_data and - image_data_len are set. - - b) 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; - guchar *image_data; /* holds the thumbnail data of - non-transfered thumbnails when - filename == NULL */ - gsize image_data_len; /* length of data */ - gpointer pixbuf; - gint rotation; /* angle (0, 90, 180, 270) to rotate the image */ - guint32 offset; - guint32 size; - gint16 width; - gint16 height; - gint16 horizontal_padding; - gint16 vertical_padding; - /* reserved for future use */ - gint32 reserved_int1; - gint32 reserved_int2; - gpointer reserved1; - gpointer reserved2; +enum _ItdbThumbDataType { + ITDB_THUMB_TYPE_INVALID, + ITDB_THUMB_TYPE_FILE, + ITDB_THUMB_TYPE_MEMORY, + ITDB_THUMB_TYPE_PIXBUF, + ITDB_THUMB_TYPE_IPOD }; +typedef enum _ItdbThumbDataType ItdbThumbDataType; + + struct _Itdb_Artwork { - GList *thumbnails; /* list of Itdb_Thumbs */ + Itdb_Thumb *thumbnail; guint32 id; /* Artwork id used by photoalbums, starts at * 0x40... libgpod will set this on sync. */ guint64 dbid; /* dbid of associated track. used @@ -1190,8 +1159,9 @@ gboolean itdb_track_set_thumbnails_from_data (Itdb_Track *track, gsize image_data_len); gboolean itdb_track_set_thumbnails_from_pixbuf (Itdb_Track *track, gpointer pixbuf); - +gboolean itdb_track_has_thumbnails (Itdb_Track *track); void itdb_track_remove_thumbnails (Itdb_Track *track); +gpointer itdb_track_get_thumbnail (Itdb_Track *track, gint width, gint height); /* photoalbum functions -- see itdb_photoalbum.c for instructions on * how to use. */ @@ -1237,25 +1207,21 @@ Itdb_PhotoAlbum *itdb_photodb_photoalbum_by_name(Itdb_PhotoDB *db, 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, +gboolean itdb_artwork_set_thumbnail (Itdb_Artwork *artwork, const gchar *filename, gint rotation, GError **error); -gboolean itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, - ItdbThumbType type, +gboolean itdb_artwork_set_thumbnail_from_data (Itdb_Artwork *artwork, const guchar *image_data, gsize image_data_len, gint rotation, GError **error); -gboolean itdb_artwork_add_thumbnail_from_pixbuf (Itdb_Artwork *artwork, - ItdbThumbType type, +gboolean itdb_artwork_set_thumbnail_from_pixbuf (Itdb_Artwork *artwork, gpointer pixbuf, gint rotation, GError **error); -void itdb_artwork_remove_thumbnail (Itdb_Artwork *artwork, - Itdb_Thumb *thumb); void itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork); +gpointer itdb_artwork_get_pixbuf (Itdb_Device *device, Itdb_Artwork *artwork, + gint width, gint height); + /* itdb_thumb_... */ /* the following function returns a pointer to a GdkPixbuf if gdk-pixbuf is installed -- a NULL pointer otherwise. */ @@ -1263,8 +1229,7 @@ gpointer itdb_thumb_get_gdk_pixbuf (Itdb_Device *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 (Itdb_Device *device, Itdb_Thumb *thumb); + /* itdb_chapterdata_... */ Itdb_Chapterdata *itdb_chapterdata_new (void); void itdb_chapterdata_free (Itdb_Chapterdata *chapterdata); diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c index acdbc7e..7891775 100644 --- a/src/itdb_artwork.c +++ b/src/itdb_artwork.c @@ -30,6 +30,7 @@ #include "itdb_device.h" #include "itdb_private.h" +#include "itdb_thumb.h" #include "db-image-parser.h" #include "itdb_endianness.h" #include @@ -71,29 +72,6 @@ void itdb_artwork_free (Itdb_Artwork *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_duplicate: * @artwork: an #Itdb_Artwork @@ -111,30 +89,13 @@ Itdb_Artwork *itdb_artwork_duplicate (Itdb_Artwork *artwork) memcpy (dup, artwork, sizeof (Itdb_Artwork)); - dup->thumbnails = dup_thumbnails (artwork->thumbnails); + if (artwork->thumbnail != NULL) { + dup->thumbnail = itdb_thumb_duplicate (artwork->thumbnail); + } return dup; } - -/** - * itdb_artwork_remove_thumbnail: - * @artwork: an #Itdb_Artwork - * @thumb: an #Itdb_Thumb - * - * Removes @thumb from @artwork. The memory used by @thumb is freed. - **/ -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); - itdb_thumb_free (thumb); -} - - /** * itdb_artwork_remove_thumbnails: * @artwork: an #Itdb_Artwork @@ -146,12 +107,10 @@ 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); + if (artwork->thumbnail != NULL) { + itdb_thumb_free (artwork->thumbnail); } + artwork->thumbnail = NULL; artwork->artwork_size = 0; artwork->id = 0; } @@ -160,7 +119,7 @@ itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork) /** - * itdb_artwork_add_thumbnail + * itdb_artwork_set_thumbnail * @artwork: an #Itdb_Thumbnail * @type: thumbnail size * @filename: image file to use to create the thumbnail @@ -180,8 +139,7 @@ itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork) * otherwise. @error is set appropriately. **/ gboolean -itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, - ItdbThumbType type, +itdb_artwork_set_thumbnail (Itdb_Artwork *artwork, const gchar *filename, gint rotation, GError **error) @@ -204,11 +162,12 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, artwork->artwork_size = statbuf.st_size; artwork->creation_date = statbuf.st_mtime; - thumb = itdb_thumb_new (); - thumb->filename = g_strdup (filename); - thumb->type = type; - thumb->rotation = rotation; - artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); + thumb = itdb_thumb_new_from_file (filename); + itdb_thumb_set_rotation (thumb, rotation); + if (artwork->thumbnail != NULL) { + itdb_thumb_free (artwork->thumbnail); + } + artwork->thumbnail = thumb; return TRUE; #else @@ -240,8 +199,7 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, * otherwise. @error is set appropriately. **/ gboolean -itdb_artwork_add_thumbnail_from_pixbuf (Itdb_Artwork *artwork, - ItdbThumbType type, +itdb_artwork_set_thumbnail_from_pixbuf (Itdb_Artwork *artwork, gpointer pixbuf, gint rotation, GError **error) @@ -264,12 +222,12 @@ itdb_artwork_add_thumbnail_from_pixbuf (Itdb_Artwork *artwork, artwork->artwork_size = rowstride * height; artwork->creation_date = time.tv_sec; - thumb = itdb_thumb_new (); - g_object_ref (G_OBJECT (pixbuf)); - thumb->pixbuf = pixbuf; - thumb->type = type; - thumb->rotation = rotation; - artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); + thumb = itdb_thumb_new_from_pixbuf (pixbuf); + itdb_thumb_set_rotation (thumb, rotation); + if (artwork->thumbnail != NULL) { + itdb_thumb_free (artwork->thumbnail); + } + artwork->thumbnail = thumb; return TRUE; #else @@ -302,8 +260,7 @@ itdb_artwork_add_thumbnail_from_pixbuf (Itdb_Artwork *artwork, * otherwise. @error is set appropriately. **/ gboolean -itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, - ItdbThumbType type, +itdb_artwork_set_thumbnail_from_data (Itdb_Artwork *artwork, const guchar *image_data, gsize image_data_len, gint rotation, @@ -322,14 +279,12 @@ itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, artwork->artwork_size = image_data_len; artwork->creation_date = time.tv_sec; - thumb = itdb_thumb_new (); - thumb->image_data = g_malloc (image_data_len); - thumb->image_data_len = image_data_len; - memcpy (thumb->image_data, image_data, image_data_len); - - thumb->type = type; - thumb->rotation = rotation; - artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); + thumb = itdb_thumb_new_from_data (image_data, image_data_len); + itdb_thumb_set_rotation (thumb, rotation); + if (artwork->thumbnail != NULL) { + itdb_thumb_free (artwork->thumbnail); + } + artwork->thumbnail = thumb; return TRUE; #else @@ -339,93 +294,6 @@ itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, #endif } - -/** - * itdb_artwork_get_thumb_by_type: - * @artwork: an #Itdb_Artwork - * @type: type of the #Itdb_Thumb to retrieve - * - * Searches @artwork for an #Itdb_Thumb of type @type. - * - * Returns: an #Itdb_Thumb of type @type, or NULL if such a thumbnail couldn't - * be found - **/ -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; -} - - -/** - * itdb_thumb_get_filename: - * @device: an #Itdb_Device - * @thumb: an #Itdb_Thumb - * - * 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. - * - * Return value: newly allocated string containing the absolute path to the - * thumbnail file. - **/ -gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb) -{ - gchar *artwork_dir, *filename=NULL; - - 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; - } - - if (!device->mountpoint) - { - 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) - { - const gchar *name_on_disk = strchr( thumb->filename+1, ':'); - if (name_on_disk) - { - filename = itdb_get_path (artwork_dir, name_on_disk + 1); - } - g_free (artwork_dir); - } - - } - return filename; -} - - #if HAVE_GDKPIXBUF static guchar * unpack_RGB_565 (guint16 *pixels, guint bytes_len, guint byte_order) @@ -772,7 +640,7 @@ unpack_UYVY (guchar *yuvdata, gint bytes_len, guint byte_order, } static guchar * -get_pixel_data (Itdb_Device *device, Itdb_Thumb *thumb) +get_pixel_data (Itdb_Device *device, Itdb_Thumb_Ipod_Item *thumb) { gchar *filename = NULL; guchar *result = NULL; @@ -787,7 +655,7 @@ get_pixel_data (Itdb_Device *device, Itdb_Thumb *thumb) */ result = g_malloc (thumb->size); - filename = itdb_thumb_get_filename (device, thumb); + filename = itdb_thumb_ipod_get_filename (device, thumb); if (!filename) { @@ -832,7 +700,7 @@ get_pixel_data (Itdb_Device *device, Itdb_Thumb *thumb) } static guchar * -itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) +itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb_Ipod_Item *item) { #if 0 #include @@ -843,15 +711,16 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) #endif void *pixels_raw; guchar *pixels=NULL; - const Itdb_ArtworkFormat *img_info; - + g_return_val_if_fail (device, NULL); - g_return_val_if_fail (thumb, NULL); - g_return_val_if_fail (thumb->size != 0, NULL); - img_info = itdb_get_artwork_info_from_type (device, thumb->type); - g_return_val_if_fail (img_info, NULL); + g_return_val_if_fail (item, NULL); + g_return_val_if_fail (item->size != 0, NULL); - pixels_raw = get_pixel_data (device, thumb); + if (item->format == NULL) { + return NULL; + } + + pixels_raw = get_pixel_data (device, item); #if 0 name = g_strdup_printf ("thumb_%03d.raw", i++); @@ -864,7 +733,7 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) return NULL; } - switch (img_info->format) + switch (item->format->format) { case THUMB_FORMAT_RGB565_LE_90: case THUMB_FORMAT_RGB565_BE_90: @@ -873,8 +742,8 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) screen photo thumbnail) */ case THUMB_FORMAT_RGB565_LE: case THUMB_FORMAT_RGB565_BE: - pixels = unpack_RGB_565 (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format)); + pixels = unpack_RGB_565 (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format)); break; case THUMB_FORMAT_RGB555_LE_90: case THUMB_FORMAT_RGB555_BE_90: @@ -883,8 +752,8 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) screen photo thumbnail) */ case THUMB_FORMAT_RGB555_LE: case THUMB_FORMAT_RGB555_BE: - pixels = unpack_RGB_555 (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format)); + pixels = unpack_RGB_555 (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format)); break; case THUMB_FORMAT_RGB888_LE_90: case THUMB_FORMAT_RGB888_BE_90: @@ -892,8 +761,8 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) different treatment */ case THUMB_FORMAT_RGB888_LE: case THUMB_FORMAT_RGB888_BE: - pixels = unpack_RGB_888 (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format)); + pixels = unpack_RGB_888 (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format)); break; case THUMB_FORMAT_REC_RGB555_LE_90: case THUMB_FORMAT_REC_RGB555_BE_90: @@ -902,29 +771,29 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) screen photo thumbnail) */ case THUMB_FORMAT_REC_RGB555_LE: case THUMB_FORMAT_REC_RGB555_BE: - pixels = unpack_rec_RGB_555 (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format), - img_info->width, img_info->height); + pixels = unpack_rec_RGB_555 (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format), + item->format->width, item->format->height); break; case THUMB_FORMAT_EXPERIMENTAL_LE: case THUMB_FORMAT_EXPERIMENTAL_BE: #if DEBUG_ARTWORK - pixels = unpack_experimental (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format), - img_info->width, img_info->height); + pixels = unpack_experimental (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format), + item->format->width, item->format->height); break; #endif case THUMB_FORMAT_UYVY_LE: case THUMB_FORMAT_UYVY_BE: - pixels = unpack_UYVY (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format), - img_info->width, img_info->height); + pixels = unpack_UYVY (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format), + item->format->width, item->format->height); break; case THUMB_FORMAT_I420_LE: case THUMB_FORMAT_I420_BE: - pixels = unpack_I420 (pixels_raw, thumb->size, - itdb_thumb_get_byteorder (img_info->format), - img_info->width, img_info->height); + pixels = unpack_I420 (pixels_raw, item->size, + itdb_thumb_get_byteorder (item->format->format), + item->format->width, item->format->height); break; } g_free (pixels_raw); @@ -932,158 +801,29 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) return pixels; } -#endif - - -/** - * itdb_thumb_get_gdk_pixbuf: - * @device: an #Itdb_Device - * @thumb: an #Itdb_Thumb - * - * Converts @thumb to a #GdkPixbuf. - * Since we want to have gdk-pixbuf dependency optional, a generic - * gpointer is returned which you have to cast to a #GdkPixbuf using - * GDK_PIXBUF() yourself. - * - * Return value: a #GdkPixbuf that must be unreffed with gdk_pixbuf_unref() - * after use, or NULL if the creation of the gdk-pixbuf failed or if - * libgpod was compiled without gdk-pixbuf support. - **/ -gpointer -itdb_thumb_get_gdk_pixbuf (Itdb_Device *device, Itdb_Thumb *thumb) +gpointer itdb_thumb_ipod_item_to_pixbuf (Itdb_Device *device, + Itdb_Thumb_Ipod_Item *item) { -#if HAVE_GDKPIXBUF - GdkPixbuf *pixbuf=NULL; - guchar *pixels; - const Itdb_ArtworkFormat *img_info=NULL; - - g_return_val_if_fail (thumb, NULL); - - /* If we are dealing with an iPod (device != NULL), use default - image dimensions as used on the iPod in question. - - If we are not dealing with an iPod, we can only return a pixmap - for thumbnails "not transferred to the iPod" (thumb->size == - 0). - */ - if (device != NULL) - { - img_info = itdb_get_artwork_info_from_type (device, thumb->type); - } - - if (thumb->size == 0) - { /* thumbnail has not yet been transferred to the iPod */ - gint width=0, height=0; - - if (img_info != NULL) - { /* use image dimensions from iPod */ - width = img_info->width; - height = img_info->height; - } - else - { /* use default dimensions */ - /* FIXME: better way to use the ipod_color dimensions? */ - switch (thumb->type) - { - case ITDB_THUMB_COVER_SMALL: - width = 56; height = 56; break; - case ITDB_THUMB_COVER_LARGE: - width = 140; height = 140; break; - case ITDB_THUMB_PHOTO_SMALL: - width = 42; height = 30; break; - case ITDB_THUMB_PHOTO_LARGE: - width = 130; height = 88; break; - case ITDB_THUMB_PHOTO_FULL_SCREEN: - width = 220; height = 176; break; - case ITDB_THUMB_PHOTO_TV_SCREEN: - width = 720; height = 480; break; - case ITDB_THUMB_COVER_XLARGE: - width = 320; height = 320; break; - case ITDB_THUMB_COVER_MEDIUM: - width = 128; height = 128; break; - case ITDB_THUMB_COVER_SMEDIUM: - width = 88; height = 88; break; - case ITDB_THUMB_COVER_XSMALL: - width = 56; height = 56; break; - case ITDB_THUMB_CHAPTER_SMALL: - width = 100; height = 100; break; - case ITDB_THUMB_CHAPTER_LARGE: - width = 200; height = 200; break; - } - if (width == 0) - { - width = 140; - height = 140; - } - } - - if (thumb->filename) - { /* read data from filename */ - pixbuf = gdk_pixbuf_new_from_file_at_size (thumb->filename, - width, height, - NULL); - } - else if (thumb->image_data) - { /* use data stored in image_data */ - GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); - g_return_val_if_fail (loader, FALSE); - gdk_pixbuf_loader_set_size (loader, - width, height); - gdk_pixbuf_loader_write (loader, - thumb->image_data, - thumb->image_data_len, - NULL); - gdk_pixbuf_loader_close (loader, NULL); - pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - if (pixbuf) - g_object_ref (pixbuf); - g_object_unref (loader); - } - else if (thumb->pixbuf) - { /* use pixbuf data */ - pixbuf = gdk_pixbuf_scale_simple (thumb->pixbuf, - width, height, - GDK_INTERP_BILINEAR); - } - - 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; - } - else - { /* pixbuf is already on the iPod -> read from there */ GdkPixbuf *pixbuf_full; GdkPixbuf *pixbuf_sub; - gint pad_x = thumb->horizontal_padding; - gint pad_y = thumb->vertical_padding; - gint width = thumb->width; - gint height = thumb->height; + GdkPixbuf *pixbuf; + gint pad_x = item->horizontal_padding; + gint pad_y = item->vertical_padding; + gint width = item->width; + gint height = item->height; + const Itdb_ArtworkFormat *img_info = item->format; + guchar *pixels; /* printf ("hp%d vp%d w%d h%d\n", pad_x, pad_y, width, height);*/ - - if (img_info == NULL) - { - g_print (_("Unable to retrieve thumbnail (appears to be on iPod, but no image info available): type: %d, filename: '%s'\n"), - thumb->type, thumb->filename); - return NULL; - } - - pixels = itdb_thumb_get_rgb_data (device, thumb); + if (item->format == NULL) { + g_warning (_("Unable to retrieve thumbnail (appears to be on iPod, but no image info available): filename: '%s'\n"), + item->filename); + return NULL; + } + pixels = itdb_thumb_get_rgb_data (device, item); if (pixels == NULL) { return NULL; @@ -1097,6 +837,7 @@ itdb_thumb_get_gdk_pixbuf (Itdb_Device *device, Itdb_Thumb *thumb) 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 !! */ @@ -1133,113 +874,39 @@ itdb_thumb_get_gdk_pixbuf (Itdb_Device *device, Itdb_Thumb *thumb) pixbuf = gdk_pixbuf_copy (pixbuf_sub); gdk_pixbuf_unref (pixbuf_full); gdk_pixbuf_unref (pixbuf_sub); - } - return pixbuf; -#else - return NULL; -#endif + return pixbuf; } - -/** - * itdb_thumb_new: - * - * Creates a new #Itdb_Thumb - * - * Return Value: newly allocated #Itdb_Thumb to be freed with itdb_thumb_free() - * after use - **/ -Itdb_Thumb *itdb_thumb_new (void) +#else +gpointer itdb_thumb_ipod_item_to_pixbuf (Itdb_Thumb_Ipod_Item *item) { - Itdb_Thumb *thumb = g_new0 (Itdb_Thumb, 1); - return thumb; + return NULL; } - -/** - * itdb_thumb_free: - * @thumb: an #Itdb_Thumb - * - * Frees the memory used by @thumb - **/ -void itdb_thumb_free (Itdb_Thumb *thumb) -{ - g_return_if_fail (thumb); - - g_free (thumb->image_data); -#ifdef HAVE_GDKPIXBUF - if (thumb->pixbuf) { - g_object_unref (G_OBJECT (thumb->pixbuf)); - } #endif - g_free (thumb->filename); - g_free (thumb); -} - -/** - * itdb_thumb_duplicate: - * @thumb: an #Itdb_Thumb +/** + * itdb_artwork_get_thumbnail! + * @artwork: an #Itdb_Artwork + * @width: width of the pixbuf to retrieve, -1 for the biggest possible size + * (with no scaling) + * @height: height of the pixbuf to retrieve, -1 for the biggest possible size + * (with no scaling) * - * Duplicates the data contained in @thumb + * Returns a #GdkPixbuf representing the thumbnail stored in @artwork + * scaling it if appropriate. If either height or width is -1, then the + * biggest unscaled thumbnail available will be returned * - * Return value: a newly allocated copy of @thumb to be freed with - * itdb_thumb_free() after use + * Return value: a #GdkPixbuf that must be unreffed when no longer used, NULL + * if no artwork could be found or if libgpod is compiled without GdkPixbuf + * support **/ -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); - - if (thumb->image_data) - { - /* image_data_len already copied with the memcpy above */ - new_thumb->image_data = g_malloc (thumb->image_data_len); - memcpy (new_thumb->image_data, thumb->image_data, - new_thumb->image_data_len); - } -#ifdef HAVE_GDKPIXBUF - if (thumb->pixbuf) { - g_object_ref (G_OBJECT (thumb->pixbuf)); - } -#endif - return new_thumb; -} - - -G_GNUC_INTERNAL gint -itdb_thumb_get_byteorder (const ItdbThumbFormat format) +gpointer itdb_artwork_get_pixbuf (Itdb_Device *device, Itdb_Artwork *artwork, + gint width, gint height) { - switch (format) - { - case THUMB_FORMAT_UYVY_LE: - case THUMB_FORMAT_I420_LE: - case THUMB_FORMAT_RGB565_LE: - case THUMB_FORMAT_RGB565_LE_90: - case THUMB_FORMAT_RGB555_LE: - case THUMB_FORMAT_RGB555_LE_90: - case THUMB_FORMAT_RGB888_LE: - case THUMB_FORMAT_RGB888_LE_90: - case THUMB_FORMAT_REC_RGB555_LE: - case THUMB_FORMAT_REC_RGB555_LE_90: - case THUMB_FORMAT_EXPERIMENTAL_LE: - return G_LITTLE_ENDIAN; - case THUMB_FORMAT_UYVY_BE: - case THUMB_FORMAT_I420_BE: - case THUMB_FORMAT_RGB565_BE: - case THUMB_FORMAT_RGB565_BE_90: - case THUMB_FORMAT_RGB555_BE: - case THUMB_FORMAT_RGB555_BE_90: - case THUMB_FORMAT_RGB888_BE: - case THUMB_FORMAT_RGB888_BE_90: - case THUMB_FORMAT_REC_RGB555_BE: - case THUMB_FORMAT_REC_RGB555_BE_90: - case THUMB_FORMAT_EXPERIMENTAL_BE: - return G_BIG_ENDIAN; + g_return_val_if_fail (artwork != NULL, NULL); + if (artwork->thumbnail == NULL) { + return NULL; } - g_return_val_if_reached (-1); + return itdb_thumb_to_pixbuf_at_size (device, artwork->thumbnail, + width, height); } diff --git a/src/itdb_device.h b/src/itdb_device.h index 1a8a70a..f6aaf14 100644 --- a/src/itdb_device.h +++ b/src/itdb_device.h @@ -46,7 +46,6 @@ G_BEGIN_DECLS -typedef struct _Itdb_ArtworkFormat Itdb_ArtworkFormat; typedef enum _ItdbThumbFormat ItdbThumbFormat; enum _ItdbThumbFormat diff --git a/src/itdb_photoalbum.c b/src/itdb_photoalbum.c index b55c4d0..614236f 100644 --- a/src/itdb_photoalbum.c +++ b/src/itdb_photoalbum.c @@ -361,7 +361,6 @@ static Itdb_Artwork *itdb_photodb_add_photo_internal (Itdb_PhotoDB *db, gboolean result; Itdb_Artwork *artwork; Itdb_PhotoAlbum *album; - const Itdb_ArtworkFormat *format; g_return_val_if_fail (db, NULL); g_return_val_if_fail (db->device, NULL); @@ -418,40 +417,21 @@ static Itdb_Artwork *itdb_photodb_add_photo_internal (Itdb_PhotoDB *db, artwork = itdb_artwork_new (); - /* Add a thumbnail for every supported format */ - format = itdb_device_get_artwork_formats (db->device); - g_return_val_if_fail (format, NULL); - - for(result = TRUE; format->type != -1 && result == TRUE; format++) + if (filename) { - if (itdb_thumb_type_is_valid_for_db (format->type, DB_TYPE_PHOTO)) - { - if (filename) - { - result = itdb_artwork_add_thumbnail (artwork, - format->type, - filename, - rotation, - error); - } - if (image_data) - { - result = itdb_artwork_add_thumbnail_from_data (artwork, - format->type, - image_data, - image_data_len, - rotation, - error); - } - if (pixbuf) - { - result = itdb_artwork_add_thumbnail_from_pixbuf (artwork, - format->type, - pixbuf, - rotation, - error); - } - } + result = itdb_artwork_set_thumbnail (artwork, filename, + rotation, error); + } + if (image_data) + { + result = itdb_artwork_set_thumbnail_from_data (artwork, image_data, + image_data_len, + rotation, error); + } + if (pixbuf) + { + result = itdb_artwork_set_thumbnail_from_pixbuf (artwork, pixbuf, + rotation, error); } if (result != TRUE) diff --git a/src/itdb_track.c b/src/itdb_track.c index c09b9ae..163ace5 100644 --- a/src/itdb_track.c +++ b/src/itdb_track.c @@ -30,6 +30,7 @@ #include "itdb_private.h" #include "itdb_device.h" +#include "itdb_thumb.h" #include static gboolean is_video_ipod (Itdb_Device *device) @@ -376,7 +377,9 @@ Itdb_Track *itdb_track_duplicate (Itdb_Track *tr) tr_dup->chapterdata = itdb_chapterdata_duplicate (tr->chapterdata); /* Copy thumbnail data */ - tr_dup->artwork = itdb_artwork_duplicate (tr->artwork); + if (tr->artwork != NULL) { + tr_dup->artwork = itdb_artwork_duplicate (tr->artwork); + } /* Copy userdata */ if (tr->userdata && tr->userdata_duplicate) @@ -395,66 +398,33 @@ static gboolean itdb_track_set_thumbnails_internal (Itdb_Track *track, gpointer *pixbuf, gint rotation, GError **error) -{ - /* gtkpod calls this function mostly with tracks that are not yet - * part of an iTunesDB. This means it is not known which - * thumbnails are required. - * - * Our solution is to add all kinds of cover thumbs and weed out - * the ones not supported when the ArtworkDB is written. - * - * Suggestions welcome! - */ - +{ gboolean result = FALSE; - ItdbThumbType thumbtypes[] = - { ITDB_THUMB_COVER_SMALL, - ITDB_THUMB_COVER_LARGE, - ITDB_THUMB_COVER_XLARGE, - ITDB_THUMB_COVER_MEDIUM, - ITDB_THUMB_COVER_SMEDIUM, - ITDB_THUMB_COVER_XSMALL, - -1 }; - ItdbThumbType *thumbtype; - const Itdb_ArtworkFormat *formats=NULL; g_return_val_if_fail (track, FALSE); g_return_val_if_fail (filename || image_data || pixbuf, FALSE); - if (track->itdb && track->itdb->device) - { - formats = itdb_device_get_artwork_formats (track->itdb->device); - } - itdb_artwork_remove_thumbnails (track->artwork); /* clear artwork id */ track->artwork->id = 0; - for (thumbtype=thumbtypes; *thumbtype!=-1; ++thumbtype) + if (filename) { - if (filename) - { - result = itdb_artwork_add_thumbnail (track->artwork, - *thumbtype, - filename, rotation, error); - } - if (image_data) - { - result = itdb_artwork_add_thumbnail_from_data (track->artwork, - *thumbtype, - image_data, - image_data_len, - rotation, error); - } - if (pixbuf) - { - result = itdb_artwork_add_thumbnail_from_pixbuf (track->artwork, - *thumbtype, - pixbuf, rotation, - error); - } - if (result == FALSE) - break; /* for (thumbtype=...) */ + result = itdb_artwork_set_thumbnail (track->artwork, filename, + rotation, error); + } + if (image_data) + { + result = itdb_artwork_set_thumbnail_from_data (track->artwork, + image_data, + image_data_len, + rotation, error); + } + if (pixbuf) + { + result = itdb_artwork_set_thumbnail_from_pixbuf (track->artwork, + pixbuf, rotation, + error); } if (result == TRUE) @@ -480,7 +450,6 @@ static gboolean itdb_track_set_thumbnails_internal (Itdb_Track *track, return result; } - /** * itdb_track_set_thumbnails: * @track: an #Itdb_Track @@ -503,9 +472,6 @@ gboolean itdb_track_set_thumbnails (Itdb_Track *track, 0, NULL); } - - - /** * itdb_track_set_thumbnails_from_data: * @track: an #Itdb_Track @@ -570,7 +536,6 @@ void itdb_track_remove_thumbnails (Itdb_Track *track) track->has_artwork = 0x02; } - /** * itdb_track_by_id: * @itdb: an #Itdb_iTunesDB @@ -611,7 +576,6 @@ static gint track_id_compare (gconstpointer a, gconstpointer b) return -1; } - /** * itdb_track_id_tree_create: * @itdb: an #Itdb_iTunesDB @@ -671,4 +635,47 @@ Itdb_Track *itdb_track_id_tree_by_id (GTree *idtree, guint32 id) return (Itdb_Track *)g_tree_lookup (idtree, &id); } +/** + * itdb_track_has_thumbnails: + * @track: an #Itdb_Track + * + * Return value: TRUE if @track has artwork available, FALSE otherwise + **/ +gboolean itdb_track_has_thumbnails (Itdb_Track *track) +{ + g_return_val_if_fail (track != NULL, FALSE); + return ((track->artwork) && (track->artwork->thumbnail)); +} + +/** + * itdb_track_get_thumbnail! + * @track: an #Itdb_Track + * @width: width of the pixbuf to retrieve, -1 for the biggest possible size + * (with no scaling) + * @height: height of the pixbuf to retrieve, -1 for the biggest possible size + * (with no scaling) + * + * Returns a #GdkPixbuf representing the cover associated with the current + * track, scaling it if appropriate. If either height or width is -1, then the + * biggest unscaled thumbnail available will be returned + * + * Return value: a #GdkPixbuf that must be unreffed when no longer used, NULL + * if no artwork could be found or if libgpod is compiled without GdkPixbuf + * support + **/ +gpointer itdb_track_get_thumbnail (Itdb_Track *track, gint width, gint height) +{ + g_return_val_if_fail (track != NULL, NULL); + if (!itdb_track_has_thumbnails (track)) { + return NULL; + } + if (track->itdb != NULL) { + return itdb_thumb_to_pixbuf_at_size (track->itdb->device, + track->artwork->thumbnail, + width, height); + } else { + return itdb_thumb_to_pixbuf_at_size (NULL, track->artwork->thumbnail, + width, height); + } +} diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index ae8630f..a123285 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -559,32 +559,27 @@ ipod_image_get_ithmb_filename (const char *mount_point, gint format_id, gint ind /* If appropriate, rotate thumb->pixbuf by the value specified in * thumb->rotation or thumb->pixbuf's EXIF orientation value. */ -static void -ithumb_writer_handle_rotation (Itdb_Thumb *thumb) { - /* Make sure @rotation is valid (0, 90, 180, 270) */ - thumb->rotation = thumb->rotation % 360; - thumb->rotation /= 90; - thumb->rotation *= 90; - - +static GdkPixbuf * +ithumb_writer_handle_rotation (GdkPixbuf *pixbuf, guint *rotation) +{ /* If the caller did not specify a rotation, and there is an orientation header present in the pixbuf (from EXIF), use that to choose a rotation. NOTE: Do this before doing any transforms on the pixbuf, or you will lose the EXIF metadata. List of orientation values: http://sylvana.net/jpegcrop/exif_orientation.html */ - if (thumb->rotation == 0) { + if (*rotation == 0) { /* In GdkPixbuf 2.12 or above, this returns the EXIF orientation value. */ - const char* exif_orientation = gdk_pixbuf_get_option(thumb->pixbuf, "orientation"); + const char* exif_orientation = gdk_pixbuf_get_option(pixbuf, "orientation"); if (exif_orientation != NULL) { switch (exif_orientation[0]) { case '3': - thumb->rotation = 180; + *rotation = 180; break; case '6': - thumb->rotation = 270; + *rotation = 270; break; case '8': - thumb->rotation = 90; + *rotation = 90; break; /* '1' means no rotation. The other four values are all various transpositions, which are rare in real photos so we don't @@ -594,21 +589,18 @@ ithumb_writer_handle_rotation (Itdb_Thumb *thumb) { } /* Rotate if necessary */ - if (thumb->rotation != 0) + if (*rotation != 0) { - GdkPixbuf *new_pixbuf = gdk_pixbuf_rotate_simple (thumb->pixbuf, thumb->rotation); - g_object_unref (thumb->pixbuf); - thumb->pixbuf = new_pixbuf; - /* Clean up */ - thumb->rotation = 0; + return gdk_pixbuf_rotate_simple (pixbuf, *rotation); } + return g_object_ref (G_OBJECT (pixbuf)); } /* On the iPhone, thumbnails are presented as squares in a grid. In order to fit the grid, they have to be cropped as well as scaled. */ static GdkPixbuf * -ithumb_writer_scale_and_crop (Itdb_Thumb *thumb, +ithumb_writer_scale_and_crop (GdkPixbuf *input_pixbuf, gint width, gint height, gboolean crop) { @@ -618,9 +610,8 @@ ithumb_writer_scale_and_crop (Itdb_Thumb *thumb, gint offset_x, offset_y; gint border_width = 0; - GdkPixbuf *input_pixbuf, *output_pixbuf; + GdkPixbuf *output_pixbuf; - input_pixbuf = GDK_PIXBUF(thumb->pixbuf); g_object_get (G_OBJECT (input_pixbuf), "width", &input_width, "height", &input_height, @@ -675,7 +666,38 @@ ithumb_writer_scale_and_crop (Itdb_Thumb *thumb, return output_pixbuf; } -static void *pack_thumbnail (iThumbWriter *writer, Itdb_Thumb *thumb, +static GdkPixbuf * +ithumb_writer_handle_pixbuf_transform (iThumbWriter *writer, + GdkPixbuf *pixbuf, guint rotation) +{ + GdkPixbuf *rotated_pixbuf; + GdkPixbuf *scaled_pixbuf; + + guint width; + guint height; + + rotated_pixbuf = ithumb_writer_handle_rotation (pixbuf, &rotation); + + if ((rotation == 0) || (rotation == 180)) + { + width = writer->img_info->width; + height = writer->img_info->height; + } + else + { + width = writer->img_info->height; + height = writer->img_info->width; + } + + scaled_pixbuf = ithumb_writer_scale_and_crop (rotated_pixbuf, width, height, + writer->img_info->crop); + g_object_unref (rotated_pixbuf); + rotated_pixbuf = NULL; + + return scaled_pixbuf; +} + +static void *pack_thumbnail (iThumbWriter *writer, Itdb_Thumb_Ipod_Item *thumb, GdkPixbuf *pixbuf) { typedef void *(*PackerFunc)(GdkPixbuf *pixbuf, @@ -726,7 +748,7 @@ static void *pack_thumbnail (iThumbWriter *writer, Itdb_Thumb *thumb, thumb->vertical_padding, &thumb->size); } -static gboolean write_pixels (iThumbWriter *writer, Itdb_Thumb *thumb, +static gboolean write_pixels (iThumbWriter *writer, Itdb_Thumb_Ipod_Item *thumb, void *pixels) { if (pixels == NULL) @@ -760,9 +782,10 @@ static gboolean write_pixels (iThumbWriter *writer, Itdb_Thumb *thumb, return TRUE; } -static char *get_ithmb_filename (iThumbWriter *writer, Itdb_Thumb *thumb) +static char *get_ithmb_filename (iThumbWriter *writer, + const Itdb_ArtworkFormat *format) { - switch (thumb->type) + switch (format->type) { case ITDB_THUMB_PHOTO_LARGE: case ITDB_THUMB_PHOTO_SMALL: @@ -788,7 +811,8 @@ static char *get_ithmb_filename (iThumbWriter *writer, Itdb_Thumb *thumb) g_return_val_if_reached (NULL); } -static void set_thumb_padding (iThumbWriter *writer, Itdb_Thumb *thumb, +static void set_thumb_padding (iThumbWriter *writer, + Itdb_Thumb_Ipod_Item *thumb, gint width, gint height) { switch (writer->db_type) @@ -826,18 +850,20 @@ static GdkPixbuf *pixbuf_from_image_data (guchar *image_data, gsize len) return pixbuf; } -static gboolean +static Itdb_Thumb_Ipod_Item * ithumb_writer_write_thumbnail (iThumbWriter *writer, Itdb_Thumb *thumb) { GdkPixbuf *pixbuf = NULL; void *pixels = NULL; gint width, height; /* must be gint -- see comment below */ + Itdb_Thumb_Ipod_Item *thumb_ipod; + GdkPixbuf *scaled_pixbuf; gboolean result; - g_return_val_if_fail (writer, FALSE); - g_return_val_if_fail (writer->img_info, FALSE); - g_return_val_if_fail (thumb, FALSE); + g_return_val_if_fail (writer, NULL); + g_return_val_if_fail (writer->img_info, NULL); + g_return_val_if_fail (thumb, NULL); /* An thumb can start with one of: 1. a filename @@ -846,84 +872,78 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, In case 1 and 2, we load the relevant data into a GdkPixbuf and proceed with case 3. */ - if (thumb->filename) - { /* read image from filename */ - thumb->pixbuf = gdk_pixbuf_new_from_file (thumb->filename, NULL); - g_free (thumb->filename); - thumb->filename = NULL; + if (thumb->data_type == ITDB_THUMB_TYPE_FILE) + { + Itdb_Thumb_File *thumb_file = (Itdb_Thumb_File *)thumb; + pixbuf = gdk_pixbuf_new_from_file (thumb_file->filename, NULL); } - else if (thumb->image_data) - { /* image data is stored in image_data and image_data_len */ - thumb->pixbuf = pixbuf_from_image_data (thumb->image_data, - thumb->image_data_len); - g_free (thumb->image_data); - thumb->image_data = NULL; - thumb->image_data_len = 0; + else if (thumb->data_type == ITDB_THUMB_TYPE_MEMORY) + { + Itdb_Thumb_Memory *thumb_mem = (Itdb_Thumb_Memory *)thumb; + pixbuf = pixbuf_from_image_data (thumb_mem->image_data, + thumb_mem->image_data_len); + } + else if (thumb->data_type == ITDB_THUMB_TYPE_PIXBUF) + { + Itdb_Thumb_Pixbuf *thumb_pixbuf = (Itdb_Thumb_Pixbuf *)thumb; + pixbuf = g_object_ref (G_OBJECT (thumb_pixbuf->pixbuf)); } - if (thumb->pixbuf == NULL) + if (pixbuf == NULL) { /* This is quite bad... if we just return FALSE the ArtworkDB gets messed up. */ - thumb->pixbuf = gdk_pixbuf_from_pixdata (&questionmark_pixdata, FALSE, NULL); + pixbuf = gdk_pixbuf_from_pixdata (&questionmark_pixdata, FALSE, NULL); - if (!thumb->pixbuf) + if (!pixbuf) { /* Somethin went wrong. let's insert a red thumbnail */ - thumb->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, writer->img_info->width, writer->img_info->height); - gdk_pixbuf_fill (thumb->pixbuf, 0xff000000); + gdk_pixbuf_fill (pixbuf, 0xff000000); } /* avoid rotation */ - thumb->rotation = 0; + itdb_thumb_set_rotation (thumb, 0); } - g_assert(thumb->pixbuf); - - ithumb_writer_handle_rotation(thumb); + g_assert(pixbuf); - /* If we rotate by 90 or 270 degrees interchange the width and - * height */ - if ((thumb->rotation == 0) || (thumb->rotation == 180)) - { - width = writer->img_info->width; - height = writer->img_info->height; - } - else - { - width = writer->img_info->height; - height = writer->img_info->width; - } - - pixbuf = ithumb_writer_scale_and_crop (thumb, width, height, - writer->img_info->crop); - g_object_unref (thumb->pixbuf); - thumb->pixbuf = NULL; + scaled_pixbuf = ithumb_writer_handle_pixbuf_transform (writer, pixbuf, itdb_thumb_get_rotation (thumb)); + g_object_unref (pixbuf); + pixbuf = 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), + g_object_get (G_OBJECT (scaled_pixbuf), "width", &width, "height", &height, NULL); - set_thumb_padding (writer, thumb, width, height); + thumb_ipod = itdb_thumb_new_item_from_ipod (writer->img_info); + g_assert (thumb_ipod != NULL); + + set_thumb_padding (writer, thumb_ipod, width, height); /* The thumbnail width/height is inclusive padding */ - thumb->width = thumb->horizontal_padding + width; - thumb->height = thumb->vertical_padding + height; - thumb->offset = writer->cur_offset; + thumb_ipod->width = thumb_ipod->horizontal_padding + width; + thumb_ipod->height = thumb_ipod->vertical_padding + height; + thumb_ipod->offset = writer->cur_offset; - pixels = pack_thumbnail (writer, thumb, pixbuf); - g_object_unref (G_OBJECT (pixbuf)); + pixels = pack_thumbnail (writer, thumb_ipod, scaled_pixbuf); + g_object_unref (G_OBJECT (scaled_pixbuf)); - thumb->filename = get_ithmb_filename (writer, thumb); - result = write_pixels (writer, thumb, pixels); + thumb_ipod->filename = get_ithmb_filename (writer, writer->img_info); + result = write_pixels (writer, thumb_ipod, pixels); g_free (pixels); - return result; + if (result == FALSE) { + itdb_thumb_free ((Itdb_Thumb*)thumb_ipod); + return NULL; + } + + return thumb_ipod; } static gboolean @@ -968,22 +988,24 @@ ithumb_writer_update (iThumbWriter *writer) static void -write_thumbnail (gpointer _writer, gpointer _artwork) +write_thumbnail (iThumbWriter *writer, + Itdb_Artwork *artwork, + Itdb_Thumb_Ipod *thumb_ipod) { - iThumbWriter *writer = _writer; - Itdb_Artwork *artwork = _artwork; - Itdb_Thumb *thumb; - - thumb = itdb_artwork_get_thumb_by_type (artwork, - writer->img_info->type); + g_assert (artwork->thumbnail->data_type != ITDB_THUMB_TYPE_IPOD); - /* size == 0 indicates a thumbnail not yet written to the - thumbnail file */ - if (thumb && (thumb->size == 0)) + if (artwork->thumbnail) { /* check if new thumbnail file has to be started */ - if (ithumb_writer_update (writer)) - ithumb_writer_write_thumbnail (writer, thumb); + if (ithumb_writer_update (writer)) { + Itdb_Thumb_Ipod_Item *item; + item = ithumb_writer_write_thumbnail (writer, + artwork->thumbnail); + if (item != NULL) { + itdb_thumb_ipod_add (thumb_ipod, item); + } + + } } } @@ -1035,7 +1057,7 @@ ithumb_writer_new (const char *mount_point, static gint offset_sort (gconstpointer a, gconstpointer b); static gint offset_sort (gconstpointer a, gconstpointer b) { - return (-(((Itdb_Thumb *)a)->offset - ((Itdb_Thumb *)b)->offset)); + return (-(((Itdb_Thumb_Ipod_Item *)a)->offset - ((Itdb_Thumb_Ipod_Item *)b)->offset)); } static gboolean ithumb_rearrange_thumbnail_file (gpointer _key, @@ -1070,7 +1092,7 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key, /* check if all thumbnails have the same size */ for (gl=thumbs; gl; gl=gl->next) { - Itdb_Thumb *img = gl->data; + Itdb_Thumb_Ipod_Item *img = gl->data; if (size == 0) size = img->size; @@ -1122,7 +1144,7 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key, /* check each thumbnail slot */ for (offset=0; gl && (offsetdata; + Itdb_Thumb_Ipod_Item *thumb = gl->data; g_return_val_if_fail (thumb, FALSE); /* Try to find a thumbnail that uses this slot */ @@ -1142,7 +1164,7 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key, /* did not find a thumbnail with matching offset -> copy data from last slot (== first element) */ GList *first_gl = g_list_first (thumbs); - Itdb_Thumb *first_thumb = first_gl->data; + Itdb_Thumb_Ipod_Item *first_thumb = first_gl->data; guint32 first_offset; g_return_val_if_fail (first_thumb, FALSE); @@ -1269,46 +1291,53 @@ ithmb_rearrange_existing_thumbnails (Itdb_DB *db, case DB_TYPE_ITUNES: for (gl=db_get_itunesdb(db)->tracks; gl; gl=gl->next) { - Itdb_Thumb *thumb; - Itdb_Track *track = gl->data; + 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_Thumb *thumb = track->artwork->thumbnail; + if (!itdb_track_has_thumbnails (track)) { + continue; + } + if (thumb->data_type == ITDB_THUMB_TYPE_IPOD) { + Itdb_Thumb_Ipod_Item *item; + item = itdb_thumb_ipod_get_item_by_type (thumb, + info); + if (item) { + filename = itdb_thumb_ipod_get_filename ( db_get_device(db), - thumb); + item); if (filename) { thumbs = g_hash_table_lookup (filenamehash, filename); thumbs = g_list_append (thumbs, thumb); g_hash_table_insert (filenamehash, filename, thumbs); } - } - } + } + } + } break; case DB_TYPE_PHOTO: for (gl=db_get_photodb(db)->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_get_device (db), - thumb); + Itdb_Thumb *thumb = artwork->thumbnail; + if (thumb == NULL) { + continue; + } + if (thumb->data_type == ITDB_THUMB_TYPE_IPOD) { + Itdb_Thumb_Ipod_Item *item; + item = itdb_thumb_ipod_get_item_by_type (thumb, info); + if (item) + { + filename = itdb_thumb_ipod_get_filename ( + db_get_device (db), item); if (filename) { thumbs = g_hash_table_lookup (filenamehash, filename); thumbs = g_list_append (thumbs, thumb); g_hash_table_insert (filenamehash, filename, thumbs); } - } + } + } } break; default: @@ -1381,7 +1410,7 @@ itdb_write_ithumb_files (Itdb_DB *db) while (format->type != -1) { iThumbWriter *writer; - if (itdb_thumb_type_is_valid_for_db (format->type, db->db_type)) + if (itdb_thumb_type_is_valid_for_db (format, db->db_type)) { ithmb_rearrange_existing_thumbnails (db, format ); writer = ithumb_writer_new (mount_point, @@ -1401,21 +1430,48 @@ itdb_write_ithumb_files (Itdb_DB *db) case DB_TYPE_ITUNES: for (it = db_get_itunesdb(db)->tracks; it != NULL; it = it->next) { Itdb_Track *track; + Itdb_Thumb_Ipod *thumb_ipod; + ItdbThumbDataType type; track = it->data; g_return_val_if_fail (track, -1); - - g_list_foreach (writers, write_thumbnail, track->artwork); + if (!itdb_track_has_thumbnails (track)) { + continue; + } + type = track->artwork->thumbnail->data_type; + if (type != ITDB_THUMB_TYPE_IPOD) { + GList *it; + thumb_ipod = (Itdb_Thumb_Ipod *)itdb_thumb_ipod_new (); + for (it = writers; it != NULL; it = it->next) { + write_thumbnail (it->data, + track->artwork, + thumb_ipod); + } + itdb_thumb_free (track->artwork->thumbnail); + track->artwork->thumbnail = (Itdb_Thumb *)thumb_ipod; + } } break; case DB_TYPE_PHOTO: for (it = db_get_photodb(db)->photos; it != NULL; it = it->next) { Itdb_Artwork *photo; + Itdb_Thumb_Ipod *thumb_ipod; + ItdbThumbDataType type; photo = it->data; g_return_val_if_fail (photo, -1); - - g_list_foreach (writers, write_thumbnail, photo); + if (photo->thumbnail == NULL) { + continue; + } + type = photo->thumbnail->data_type; + if (type != ITDB_THUMB_TYPE_IPOD) { + thumb_ipod = (Itdb_Thumb_Ipod *)itdb_thumb_ipod_new (); + for (it = writers; it != NULL; it = it->next) { + write_thumbnail (it->data, photo, thumb_ipod); + } + itdb_thumb_free (photo->thumbnail); + photo->thumbnail = (Itdb_Thumb *)thumb_ipod; + } } break; default: diff --git a/tests/test-covers.c b/tests/test-covers.c index 36a87fa..195f907 100644 --- a/tests/test-covers.c +++ b/tests/test-covers.c @@ -30,43 +30,55 @@ #include #include - +#include "itdb_thumb.h" static void -save_itdb_thumb (Itdb_iTunesDB *itdb, Itdb_Thumb *thumb, const char *filename) +save_itdb_thumb (Itdb_Track *track, GdkPixbuf *pixbuf, guint id) { - GdkPixbuf *pixbuf; - - 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); */ - } + char *filename; + gint width; + gint height; + + g_object_get (G_OBJECT (pixbuf), + "width", &width, + "height", &height, + NULL); + filename = g_strdup_printf ("%03d_%s-%s-%s-%xx%x-%016"G_GINT64_MODIFIER"x.png", + id, + track->artist, track->album, + track->title, width, height, + track->dbid); + if (filename == NULL) { + return; + } + g_print (" %s\n", filename); + gdk_pixbuf_save (pixbuf, filename, "png", NULL, NULL); + gdk_pixbuf_unref (pixbuf); + /* g_print ("Saved %s\n", filename); */ + g_free (filename); } + static void save_song_thumbnails (Itdb_Track *song) { - static gint count = 0; - GList *it; - for (it = song->artwork->thumbnails; it != NULL; it = it->next) { - Itdb_Thumb *thumb; - gchar *filename; - - thumb = (Itdb_Thumb *)it->data; - g_return_if_fail (thumb); - - filename = g_strdup_printf ("%03d_%s-%s-%s-%d-%016"G_GINT64_MODIFIER"x.png", - count++, - song->artist, song->album, - song->title, thumb->type, - song->dbid); - if (filename != NULL) { - g_print (" %s\n", filename); - save_itdb_thumb (song->itdb, thumb, filename); - g_free (filename); - } + static guint count = 0; + GList *it; + GList *thumbs; + Itdb_Thumb_Ipod *thumb = (Itdb_Thumb_Ipod*)song->artwork->thumbnail; + if (thumb == NULL) { + return; + } + thumbs = itdb_thumb_ipod_to_pixbufs (song->itdb->device, thumb); + for (it = thumbs; it != NULL; it = it->next) { + GdkPixbuf *pixbuf; + + pixbuf = GDK_PIXBUF (it->data); + g_return_if_fail (pixbuf); + + save_itdb_thumb (song, pixbuf, count); + count++; } + g_list_free (thumbs); } diff --git a/tests/test-photos.c b/tests/test-photos.c index af98b1c..02ecaa3 100644 --- a/tests/test-photos.c +++ b/tests/test-photos.c @@ -31,6 +31,8 @@ #include #include +#include "itdb_thumb.h" + static void usage (int argc, char **argv) { /* gchar *name = argv[0];*/ @@ -59,41 +61,34 @@ static Itdb_Artwork *get_photo_by_id (Itdb_PhotoDB *db, guint32 id) return NULL; } -static void -save_itdb_thumb (Itdb_PhotoDB *itdb, Itdb_Thumb *thumb, - const gchar *filename) -{ - GdkPixbuf *pixbuf; - - pixbuf = itdb_thumb_get_gdk_pixbuf (itdb->device, thumb); - - if (pixbuf != NULL) { - gdk_pixbuf_save (pixbuf, filename, "png", NULL, NULL); - gdk_pixbuf_unref (pixbuf); - } -} - static void dump_thumbs (Itdb_PhotoDB *db, Itdb_Artwork *artwork, const gchar *album_name, const gchar *dir) { GList *it; gint i = 0; + GList *thumbnails; + Itdb_Thumb_Ipod *thumb; - for (it = artwork->thumbnails; it != NULL; it = it->next, i++) { - Itdb_Thumb *thumb; + thumb = (Itdb_Thumb_Ipod *)artwork->thumbnail; + thumbnails = itdb_thumb_ipod_to_pixbufs (db->device, thumb); + for (it = thumbnails; it != NULL; it = it->next, i++) { gchar *filename, *path; + GdkPixbuf *pixbuf; - thumb = (Itdb_Thumb *)it->data; - g_return_if_fail (thumb); + pixbuf = GDK_PIXBUF (it->data); + + g_return_if_fail (pixbuf); filename = g_strdup_printf ("%s-%d-%d.png", album_name, artwork->id, i ); path = g_build_filename (dir, filename, NULL); g_free (filename); - save_itdb_thumb (db, thumb, path); + gdk_pixbuf_save (pixbuf, path, "png", NULL, NULL); + gdk_pixbuf_unref (pixbuf); g_free (path); } + g_list_free (thumbnails); } static void -- cgit