summaryrefslogtreecommitdiffstats
path: root/src/ithumb-writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ithumb-writer.c')
-rw-r--r--src/ithumb-writer.c177
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;
}