summaryrefslogtreecommitdiffstats
path: root/src/ithumb-writer.c
diff options
context:
space:
mode:
authorJorg Schuler <jcsjcs@users.sourceforge.net>2005-12-04 10:26:14 +0000
committerJorg Schuler <jcsjcs@users.sourceforge.net>2005-12-04 10:26:14 +0000
commit6ef63990060d869c403cf83530d66f692ab7d5c7 (patch)
tree7eac4aa4ced55f837717d3833ffac57cd7eae044 /src/ithumb-writer.c
parentf5c2c29c13cc373fe944bb8a5598001acc5dc21f (diff)
downloadlibgpod-tmz-6ef63990060d869c403cf83530d66f692ab7d5c7.tar.gz
libgpod-tmz-6ef63990060d869c403cf83530d66f692ab7d5c7.tar.xz
libgpod-tmz-6ef63990060d869c403cf83530d66f692ab7d5c7.zip
* src/itdb_track.c: take care of artwork_size/_count a little
better, take care of dbid2 a little better. * src/ithumb-writer.c: new ithumb_rearrange_thumbnail_file() taking into account multiple references to the same slot. ithumb-writer now cleans up 0 Byte files. git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1187 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src/ithumb-writer.c')
-rw-r--r--src/ithumb-writer.c177
1 files changed, 129 insertions, 48 deletions
diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c
index c440226..d354c32 100644
--- a/src/ithumb-writer.c
+++ b/src/ithumb-writer.c
@@ -44,6 +44,7 @@
struct _iThumbWriter {
off_t cur_offset;
FILE *f;
+ gchar *filename;
IpodArtworkFormat *img_info;
GHashTable *cache;
};
@@ -102,12 +103,12 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height)
static char *
-ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id)
+ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id, gint index)
{
char *paths[] = {"iPod_Control", "Artwork", NULL, NULL};
char *filename, *buf;
- buf = g_strdup_printf ("F%04u_1.ithmb", correlation_id);
+ buf = g_strdup_printf ("F%04u_%d.ithmb", correlation_id, index);
paths[2] = buf;
@@ -242,7 +243,8 @@ ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info)
g_free, NULL);
filename = ipod_image_get_ithmb_filename (mount_point,
- info->correlation_id);
+ info->correlation_id,
+ 1);
if (filename == NULL) {
g_hash_table_destroy (writer->cache);
g_free (writer->img_info);
@@ -259,7 +261,7 @@ ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info)
return NULL;
}
writer->cur_offset = ftell (writer->f);
- g_free (filename);
+ writer->filename=filename;
return writer;
}
@@ -268,9 +270,14 @@ static void
ithumb_writer_free (iThumbWriter *writer)
{
g_return_if_fail (writer != NULL);
+ fclose (writer->f);
+ if (writer->cur_offset == 0)
+ { /* Remove empty file */
+ unlink (writer->filename);
+ }
g_hash_table_destroy (writer->cache);
g_free (writer->img_info);
- fclose (writer->f);
+ g_free (writer->filename);
g_free (writer);
}
@@ -282,17 +289,17 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
auto gint offset_sort (gconstpointer a, gconstpointer b);
gint offset_sort (gconstpointer a, gconstpointer b)
{
- return (((Itdb_Thumb *)a)->offset -
- ((Itdb_Thumb *)b)->offset);
+ return (-(((Itdb_Thumb *)a)->offset -
+ ((Itdb_Thumb *)b)->offset));
}
- gchar *filename = _key;
+ const 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;
+ guint32 offset;
void *buf = NULL;
/* printf ("%s: %d\n", filename, g_list_length (thumbs)); */
@@ -301,6 +308,15 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
if (*result == FALSE)
goto out;
+ if (thumbs == NULL)
+ { /* no thumbnails for this file --> remove altogether */
+ if (unlink (filename) == -1)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ }
+
/* check if all thumbnails have the same size */
for (gl=thumbs; gl; gl=gl->next)
{
@@ -314,30 +330,27 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
goto out;
}
}
+ if (size == 0)
+ {
+ *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)
+ if (((guint32)(statbuf.st_size / size))*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)
{
@@ -345,34 +358,48 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
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);
-
/* size is either a value coming from a hardcoded const array from
* libipoddevice, or a guint32 read from an iPod file, so no overflow
* can occur here
*/
buf = g_malloc (size);
- for (i=0; i<tn_num; ++i)
+ /* Sort the list of thumbs in reverse order of img->offset */
+ thumbs = g_list_sort (thumbs, offset_sort);
+
+ gl = g_list_last (thumbs);
+
+ /* check each thumbnail slot */
+ for (offset=0; gl && (offset<statbuf.st_size); offset+=size)
{
- 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);
+ Itdb_Thumb *thumb = gl->data;
+ g_return_val_if_fail (thumb, FALSE);
+
+ /* Try to find a thumbnail that uses this slot */
+ while ((gl != NULL) && (thumb->offset < offset))
+ {
+ gl = gl->prev;
+ if (gl)
+ thumb = gl->data;
+ g_return_val_if_fail (thumb, FALSE);
+ }
+
+ if (!gl)
+ break; /* offset now indicates new length of file */
+
+ if (thumb->offset > offset)
+ {
+ /* 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;
+ guint32 first_offset;
+
+ g_return_val_if_fail (first_thumb, FALSE);
+ first_offset = first_thumb->offset;
/* actually copy the data */
- if (lseek (fd, img->offset, SEEK_SET) != img->offset)
+ if (lseek (fd, first_offset, SEEK_SET) != first_offset)
{
*result = FALSE;
goto out;
@@ -393,19 +420,52 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
goto out;
}
- img->offset = offset;
+ /* Adjust offset of all thumbnails whose offset is
+ first_offset. Since the list is sorted, they are all at
+ the beginning of the list. */
+ while (first_thumb->offset == first_offset)
+ {
+ first_thumb->offset = offset;
+ /* There's a possibility that gl is the first
+ element. In that case don't attempt to move it (it
+ wouldn't work as intended because we access
+ gl->next after removing it from the list) */
+ if (gl != first_gl)
+ {
+ thumbs = g_list_delete_link (thumbs, first_gl);
+ /* Insert /behind/ gl */
+ thumbs = g_list_insert_before (thumbs,
+ gl->next, first_thumb);
+ first_gl = g_list_first (thumbs);
+ first_thumb = first_gl->data;
+ g_return_val_if_fail (first_thumb, FALSE);
+ }
+ }
}
}
- /* truncate the file */
- if (ftruncate (fd, tn_num*size) == -1)
- {
- *result = FALSE;
- goto out;
+ /* offset corresponds to the new length of the file */
+ if (offset > 0)
+ { /* Truncate */
+ if (ftruncate (fd, offset) == -1)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ }
+ else
+ { /* Remove file altogether */
+ close (fd);
+ fd = -1;
+ if (unlink (filename) == -1)
+ {
+ *result = FALSE;
+ goto out;
+ }
}
out:
if (fd != -1) close (fd);
- if (buf) g_free (buf);
+ g_free (buf);
g_list_free (thumbs);
return TRUE;
}
@@ -435,6 +495,9 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
GList *gl;
GHashTable *filenamehash;
gboolean result = TRUE;
+ GList *thumbs;
+ gint i;
+ gchar *filename;
g_return_val_if_fail (itdb, FALSE);
g_return_val_if_fail (info, FALSE);
@@ -457,9 +520,8 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
info->type);
if (thumb && thumb->filename && (thumb->size != 0))
{
- GList *thumbs;
- gchar *filename = itdb_thumb_get_filename (itdb->device,
- thumb);
+ filename = itdb_thumb_get_filename (itdb->device,
+ thumb);
if (filename)
{
thumbs = g_hash_table_lookup (filenamehash, filename);
@@ -469,6 +531,25 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
}
}
+ /* Check for files present on the iPod but no longer referenced by
+ thumbs */
+
+ for (i=0; i<10; ++i)
+ {
+ filename = ipod_image_get_ithmb_filename (itdb->mountpoint,
+ info->correlation_id,
+ i);
+ if (g_file_test (filename, G_FILE_TEST_EXISTS))
+ {
+ if (g_hash_table_lookup (filenamehash, filename) == NULL)
+ {
+ g_hash_table_insert (filenamehash,
+ g_strdup (filename), NULL);
+ }
+ }
+ g_free (filename);
+ }
+
g_hash_table_foreach_remove (filenamehash,
ithumb_rearrange_thumbnail_file, &result);
g_hash_table_destroy (filenamehash);