changeset 1203:43bfcbb62cd6

prepared infrastructure for delayed metadata writting - refreshing metadata immediately before writting is now possible modified metadata are stored in fd->modified_xmp
author nadvornik
date Mon, 15 Dec 2008 22:47:31 +0000
parents 8bf3fff49ddd
children fa91098e4949
files src/exif-common.c src/exif.c src/exif.h src/exiv2.cc src/metadata.c src/typedefs.h
diffstat 6 files changed, 122 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/src/exif-common.c	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/exif-common.c	Mon Dec 15 22:47:31 2008 +0000
@@ -627,10 +627,27 @@
 			}
 		}
 
-	fd->exif = exif_read(fd->path, sidecar_path);
+	fd->exif = exif_read(fd->path, sidecar_path, fd->modified_xmp);
 	return fd->exif;
 }
 
+gint exif_write_fd(FileData *fd)
+{
+	gint success;
+	ExifData *exif;
+	
+	/*  exif_read_fd can either use cached metadata which have fd->modified_xmp already applied 
+	                             or read metadata from file and apply fd->modified_xmp
+	    metadata are read also if the file was modified meanwhile */
+	exif = exif_read_fd(fd); 
+	if (!exif) return FALSE;
+	success = exif_write(exif); /* write modified metadata */
+	exif_free_fd(fd, exif);
+	g_hash_table_destroy(fd->modified_xmp);
+	fd->modified_xmp = NULL;
+	return success;
+}
+
 void exif_free_fd(FileData *fd, ExifData *exif)
 {
 	if (!fd) return;
--- a/src/exif.c	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/exif.c	Mon Dec 15 22:47:31 2008 +0000
@@ -1209,7 +1209,7 @@
 	g_free(exif);
 }
 
-ExifData *exif_read(gchar *path, gchar *sidecar_path)
+ExifData *exif_read(gchar *path, gchar *sidecar_path, GHashTable *modified_xmp)
 {
 	ExifData *exif;
 	gpointer f;
@@ -1584,22 +1584,12 @@
 	return 0;
 }
 
-ExifItem *exif_add_item(ExifData *exif, const gchar *key)
-{
-	return NULL;
-}
 
-gint exif_item_delete(ExifData *exif, ExifItem *item)
+gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values)
 {
 	return 0;
 }
 
-gint exif_item_set_string(ExifItem *item, const gchar *str)
-{
-	return 0;
-}
-
-
 typedef struct _UnmapData UnmapData;
 struct _UnmapData
 {
--- a/src/exif.h	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/exif.h	Mon Dec 15 22:47:31 2008 +0000
@@ -107,10 +107,11 @@
  *-----------------------------------------------------------------------------
  */
 
-ExifData *exif_read(gchar *path, gchar *sidecar_path);
+ExifData *exif_read(gchar *path, gchar *sidecar_path, GHashTable *modified_xmp);
 
 ExifData *exif_read_fd(FileData *fd);
 void exif_free_fd(FileData *fd, ExifData *exif);
+gint exif_write_fd(FileData *fd);
 
 /* exif_read returns processed data (merged from image and sidecar, etc.)
    this function gives access to the original data from the image.
@@ -125,7 +126,6 @@
 ExifRational *exif_get_rational(ExifData *exif, const gchar *key, gint *sign);
 
 ExifItem *exif_get_item(ExifData *exif, const gchar *key);
-ExifItem *exif_add_item(ExifData *exif, const gchar *key);
 ExifItem *exif_get_first_item(ExifData *exif);
 ExifItem *exif_get_next_item(ExifData *exif);
 
@@ -148,8 +148,7 @@
 
 gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_valid);
 
-gint exif_item_delete(ExifData *exif, ExifItem *item);
-gint exif_item_set_string(ExifItem *item, const gchar *str);
+gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values);
 
 guchar *exif_get_color_profile(ExifData *exif, guint *data_len);
 
--- a/src/exiv2.cc	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/exiv2.cc	Mon Dec 15 22:47:31 2008 +0000
@@ -201,6 +201,10 @@
 	}
 };
 
+extern "C" {
+static void _ExifDataProcessed_update_xmp(gpointer key, gpointer value, gpointer data);
+}
+
 // This allows read-write access to the metadata
 struct _ExifDataProcessed : public _ExifData
 {
@@ -215,7 +219,7 @@
 #endif
 
 public:
-	_ExifDataProcessed(gchar *path, gchar *sidecar_path)
+	_ExifDataProcessed(gchar *path, gchar *sidecar_path, GHashTable *modified_xmp)
 	{
 		imageData_ = new _ExifDataOriginal(path);
 		sidecarData_ = NULL;
@@ -233,6 +237,10 @@
 #if EXIV2_TEST_VERSION(0,17,0)
 		syncExifWithXmp(exifData_, xmpData_);
 #endif
+		if (modified_xmp)
+			{
+			g_hash_table_foreach(modified_xmp, _ExifDataProcessed_update_xmp, this);
+			}
 	}
 
 	virtual ~_ExifDataProcessed()
@@ -326,11 +334,16 @@
 
 extern "C" {
 
-ExifData *exif_read(gchar *path, gchar *sidecar_path)
+static void _ExifDataProcessed_update_xmp(gpointer key, gpointer value, gpointer data)
+{
+	exif_update_metadata((ExifData *)data, (gchar *)key, (GList *)value);
+}
+
+ExifData *exif_read(gchar *path, gchar *sidecar_path, GHashTable *modified_xmp)
 {
 	DEBUG_1("exif read %s, sidecar: %s", path, sidecar_path ? sidecar_path : "-");
 	try {
-		return new _ExifDataProcessed(path, sidecar_path);
+		return new _ExifDataProcessed(path, sidecar_path, modified_xmp);
 	}
 	catch (Exiv2::AnyError& e) {
 		std::cout << "Caught Exiv2 exception '" << e << "'\n";
@@ -731,48 +744,70 @@
 	}
 }
 
-int exif_item_set_string(ExifItem *item, const char *str)
+gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values)
 {
 	try {
-		if (!item) return 0;
-		((Exiv2::Metadatum *)item)->setValue(std::string(str));
+		const GList *work = values;
+
+		Exiv2::Metadatum *item = NULL;
+		try {
+			Exiv2::ExifKey ekey(key);
+			
+			Exiv2::ExifData::iterator pos = exif->exifData().findKey(ekey);
+			while (pos != exif->exifData().end())
+				{
+				exif->exifData().erase(pos);
+				pos = exif->exifData().findKey(ekey);
+				}
+
+			while (work)
+				{
+				exif->exifData()[key] = (gchar *)work->data;
+				work = work->next;
+				}
+		}
+		catch (Exiv2::AnyError& e) {
+			try {
+				Exiv2::IptcKey ekey(key);
+				Exiv2::IptcData::iterator pos = exif->iptcData().findKey(ekey);
+				while (pos != exif->iptcData().end())
+					{
+					exif->iptcData().erase(pos);
+					pos = exif->iptcData().findKey(ekey);
+					}
+
+				while (work)
+					{
+					exif->iptcData()[key] = (gchar *)work->data;
+					work = work->next;
+					}
+			}
+			catch (Exiv2::AnyError& e) {
+#if EXIV2_TEST_VERSION(0,16,0)
+				Exiv2::XmpKey ekey(key);
+				Exiv2::XmpData::iterator pos = exif->xmpData().findKey(ekey);
+				while (pos != exif->xmpData().end())
+					{
+					exif->xmpData().erase(pos);
+					pos = exif->xmpData().findKey(ekey);
+					}
+
+				while (work)
+					{
+					exif->xmpData()[key] = (gchar *)work->data;
+					work = work->next;
+					}
+#endif
+			}
+		}
 		return 1;
-		}
+	}
 	catch (Exiv2::AnyError& e) {
+		std::cout << "Caught Exiv2 exception '" << e << "'\n";
 		return 0;
 	}
 }
 
-int exif_item_delete(ExifData *exif, ExifItem *item)
-{
-	try {
-		if (!item) return 0;
-		for (Exiv2::ExifData::iterator i = exif->exifData().begin(); i != exif->exifData().end(); ++i) {
-			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->exifData().erase(i);
-				return 1;
-			}
-		}
-		for (Exiv2::IptcData::iterator i = exif->iptcData().begin(); i != exif->iptcData().end(); ++i) {
-			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->iptcData().erase(i);
-				return 1;
-			}
-		}
-#if EXIV2_TEST_VERSION(0,16,0)
-		for (Exiv2::XmpData::iterator i = exif->xmpData().begin(); i != exif->xmpData().end(); ++i) {
-			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->xmpData().erase(i);
-				return 1;
-			}
-		}
-#endif
-		return 0;
-	}
-	catch (Exiv2::AnyError& e) {
-		return 0;
-	}
-}
 
 void exif_add_jpeg_color_profile(ExifData *exif, unsigned char *cp_data, guint cp_length)
 {
--- a/src/metadata.c	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/metadata.c	Mon Dec 15 22:47:31 2008 +0000
@@ -30,6 +30,26 @@
 } MetadataKey;
 
 
+gint metadata_write_list(FileData *fd, const gchar *key, GList *values)
+{
+	if (!fd->modified_xmp)
+		{
+		fd->modified_xmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)string_list_free);
+		}
+	g_hash_table_insert(fd->modified_xmp, g_strdup(key), values);
+	if (fd->exif)
+		{
+		exif_update_metadata(fd->exif, key, values);
+		}
+	return TRUE;
+}
+	
+gint metadata_write_string(FileData *fd, const gchar *key, const char *value)
+{
+	return metadata_write_list(fd, key, g_list_append(NULL, g_strdup(value)));
+}
+
+
 /*
  *-------------------------------------------------------------------
  * keyword / comment read/write
@@ -341,46 +361,16 @@
 
 static gint metadata_xmp_write(FileData *fd, GList *keywords, const gchar *comment)
 {
-	gint success;
+	gint success = TRUE;
 	gint write_comment = (comment && comment[0]);
-	ExifData *exif;
-	ExifItem *item;
-
-	exif = exif_read_fd(fd);
-	if (!exif) return FALSE;
-
-	item = exif_get_item(exif, COMMENT_KEY);
-	if (item && !write_comment)
-		{
-		exif_item_delete(exif, item);
-		item = NULL;
-		}
-
-	if (!item && write_comment) item = exif_add_item(exif, COMMENT_KEY);
-	if (item) exif_item_set_string(item, comment);
 
-	while ((item = exif_get_item(exif, KEYWORD_KEY)))
-		{
-		exif_item_delete(exif, item);
-		}
-
-	if (keywords)
-		{
-		GList *work;
-
-		item = exif_add_item(exif, KEYWORD_KEY);
+	if (write_comment) success = success && metadata_write_string(fd, COMMENT_KEY, comment);
+	
+	if (keywords) success = success && metadata_write_list(fd, KEYWORD_KEY, string_list_copy(keywords));
 
-		work = keywords;
-		while (work)
-			{
-			exif_item_set_string(item, (gchar *) work->data);
-			work = work->next;
-			}
-		}
 
-	success = exif_write(exif);
-
-	exif_free_fd(fd, exif);
+/* FIXME - actual writting should be triggered in metadata_write_list and should be delayed */
+	success = exif_write_fd(fd);
 
 	return success;
 }
--- a/src/typedefs.h	Mon Dec 15 18:04:42 2008 +0000
+++ b/src/typedefs.h	Mon Dec 15 22:47:31 2008 +0000
@@ -440,6 +440,7 @@
 	gint exif_orientation;
 	
 	ExifData *exif;
+	GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values
 };
 
 struct _LayoutWindow