diff options
Diffstat (limited to 'src/ithumb-writer.c')
-rw-r--r-- | src/ithumb-writer.c | 177 |
1 files changed, 97 insertions, 80 deletions
diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index 95521b0..075a9dc 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -35,18 +35,10 @@ #include <string.h> #include <gdk-pixbuf/gdk-pixbuf.h> -#define FULL_THUMB_SIDE_LEN 0x8c -#define NOW_PLAYING_THUMB_SIDE_LEN 0x38 - -#define IPOD_THUMBNAIL_FULL_SIZE_CORRELATION_ID 1016 -#define IPOD_THUMBNAIL_NOW_PLAYING_CORRELATION_ID 1017 - struct _iThumbWriter { off_t cur_offset; FILE *f; - guint correlation_id; - enum ItdbImageType type; - int size; + IpodArtworkFormat *img_info; GHashTable *cache; }; typedef struct _iThumbWriter iThumbWriter; @@ -56,9 +48,8 @@ typedef struct _iThumbWriter iThumbWriter; * here to specify which size we are interested in in case the pixbuf is non * square */ -static void -pack_RGB_565 (GdkPixbuf *pixbuf, int size, - gushort **pixels565, unsigned int *bytes_len) +static gushort * +pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height) { guchar *pixels; gushort *result; @@ -69,17 +60,15 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int size, gint w; gint h; - g_return_if_fail (pixels565 != NULL); - *pixels565 = NULL; - g_return_if_fail (bytes_len != NULL); - g_object_get (G_OBJECT (pixbuf), "rowstride", &row_stride, "n-channels", &channels, "height", &height, "width", &width, "pixels", &pixels, NULL); - g_return_if_fail ((width <= size) && (height <= size)); - result = g_malloc0 (size * size * 2); - + 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; @@ -95,12 +84,10 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int size, r = (r << RED_SHIFT) & RED_MASK; g = (g << GREEN_SHIFT) & GREEN_MASK; b = (b << BLUE_SHIFT) & BLUE_MASK; - result[h*size + w] = (GINT16_TO_LE (r | g | b)); + result[h*dst_width + w] = (GINT16_TO_LE (r | g | b)); } } - - *pixels565 = result; - *bytes_len = size * size * 2; + return result; } @@ -141,31 +128,28 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, return NULL; } - thumb = gdk_pixbuf_new_from_file_at_size (filename, writer->size, - writer->size, NULL); + 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, NULL); - if (image->height > writer->size) { - g_object_unref (thumb); - thumb = gdk_pixbuf_new_from_file_at_size (filename, - writer->size, - writer->size, - 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->type; - pack_RGB_565 (thumb, writer->size, &pixels, &image->size); + 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); @@ -185,17 +169,21 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, } -#define FULL_THUMB_SIDE_LEN 0x8c -#define NOW_PLAYING_THUMB_SIDE_LEN 0x38 - -#define FULL_THUMB_CORRELATION_ID 1016 -#define NOW_PLAYING_THUMB_CORRELATION_ID 1017 +static char * +ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id) +{ + char *paths[] = {"iPod_Control", "Artwork", NULL, NULL}; + char *filename; + 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; +} static iThumbWriter * -ithumb_writer_new (const char *mount_point, enum ItdbImageType type, - int correlation_id, int size) +ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info) { char *filename; iThumbWriter *writer; @@ -203,18 +191,23 @@ ithumb_writer_new (const char *mount_point, enum ItdbImageType type, if (writer == NULL) { return NULL; } - writer->correlation_id = correlation_id; - writer->size = size; - writer->type = type; + 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, correlation_id); + filename = ipod_image_get_ithmb_filename (mount_point, + info->correlation_id); if (filename == NULL) { g_hash_table_destroy (writer->cache); + g_free (writer->img_info); g_free (writer); return NULL; } @@ -223,6 +216,7 @@ ithumb_writer_new (const char *mount_point, enum ItdbImageType type, g_print ("Error opening %s: %s\n", filename, strerror (errno)); g_free (filename); g_hash_table_destroy (writer->cache); + g_free (writer->img_info); g_free (writer); return NULL; } @@ -236,38 +230,74 @@ ithumb_writer_free (iThumbWriter *writer) { g_return_if_fail (writer != NULL); g_hash_table_destroy (writer->cache); + g_free (writer->img_info); fclose (writer->f); g_free (writer); } + +static void +write_thumbnail (gpointer data, gpointer user_data) +{ + iThumbWriter *writer; + Itdb_Track *song; + Itdb_Image *thumb; + + song = (Itdb_Track *)user_data; + writer = (iThumbWriter *)data; + + thumb = ithumb_writer_write_thumbnail (writer, + song->orig_image_filename); + if (thumb != NULL) { + song->thumbnails = g_list_append (song->thumbnails, thumb); + song->artwork_count++; + } +} + + G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point) { + GList *writers; GList *it; - iThumbWriter *fullsize_writer; - iThumbWriter *nowplaying_writer; + const IpodArtworkFormat *format; /* g_print ("%s\n", G_GNUC_FUNCTION);*/ - fullsize_writer = ithumb_writer_new (mount_point, - ITDB_IMAGE_FULL_SCREEN, - FULL_THUMB_CORRELATION_ID, - FULL_THUMB_SIDE_LEN); - if (fullsize_writer == NULL) { + + if (db->device == NULL) { return -1; } - nowplaying_writer = ithumb_writer_new (mount_point, - ITDB_IMAGE_NOW_PLAYING, - NOW_PLAYING_THUMB_CORRELATION_ID, - NOW_PLAYING_THUMB_SIDE_LEN); - if (nowplaying_writer == NULL) { - ithumb_writer_free (fullsize_writer); + g_object_get (G_OBJECT (db->device), "artwork-formats", + &format, NULL); + if (format == NULL) { + return -1; + } + + writers = NULL; + while (format->type != -1) { + iThumbWriter *writer; + + switch (format->type) { + case IPOD_COVER_SMALL: + case IPOD_COVER_LARGE: + writer = ithumb_writer_new (mount_point, format); + if (writer != NULL) { + writers = g_list_prepend (writers, writer); + } + break; + default: + break; + } + format++; + } + + if (writers == NULL) { return -1; } for (it = db->tracks; it != NULL; it = it->next) { Itdb_Track *song; - Itdb_Image *thumb; song = (Itdb_Track *)it->data; song->artwork_count = 0; @@ -275,24 +305,11 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point) if (song->orig_image_filename == NULL) { continue; } - thumb = ithumb_writer_write_thumbnail (nowplaying_writer, - song->orig_image_filename); - if (thumb != NULL) { - song->thumbnails = g_list_append (song->thumbnails, - thumb); - song->artwork_count++; - } - thumb = ithumb_writer_write_thumbnail (fullsize_writer, - song->orig_image_filename); - if (thumb != NULL) { - song->thumbnails = g_list_append (song->thumbnails, - thumb); - song->artwork_count++; - } + g_list_foreach (writers, write_thumbnail, song); } - ithumb_writer_free (nowplaying_writer); - ithumb_writer_free (fullsize_writer); + g_list_foreach (writers, (GFunc)ithumb_writer_free, NULL); + g_list_free (writers); return 0; } |