changeset 188:0584cb78aa14

write comment and keywords to xmp, sidecars are used if exist
author nadvornik
date Sun, 16 Mar 2008 10:32:52 +0000
parents 9eafc4957f1a
children deea9e11f1d4
files src/bar_exif.c src/bar_info.c src/bar_info.h src/cache-loader.c src/exif-common.c src/exif.c src/exif.h src/exiv2.cc src/filelist.c src/image.c src/pan-view.c src/search.c
diffstat 12 files changed, 229 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/bar_exif.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/bar_exif.c	Sun Mar 16 10:32:52 2008 +0000
@@ -172,7 +172,7 @@
 	ExifData *exif;
 	gint len, i;
 
-	exif = exif_read(eb->fd->path, FALSE);
+	exif = exif_read_fd(eb->fd, FALSE);
 
 	if (!exif)
 		{
--- a/src/bar_info.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/bar_info.c	Sun Mar 16 10:32:52 2008 +0000
@@ -11,6 +11,8 @@
 
 
 #include "gqview.h"
+#include "exif.h"
+
 #include "bar_info.h"
 
 #include "cache.h"
@@ -47,7 +49,7 @@
  *-------------------------------------------------------------------
  */
 
-gint comment_write(gchar *path, GList *keywords, const gchar *comment)
+static gint comment_file_write(gchar *path, GList *keywords, const gchar *comment)
 {
 	FILE *f;
 
@@ -76,7 +78,7 @@
 	return TRUE;
 }
 
-gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment)
+static gint comment_legacy_write(FileData *fd, GList *keywords, const gchar *comment)
 {
 	gchar *comment_path;
 	gint success = FALSE;
@@ -113,7 +115,7 @@
 
 		comment_pathl = path_from_utf8(comment_path);
 
-		success = comment_write(comment_pathl, keywords, comment);
+		success = comment_file_write(comment_pathl, keywords, comment);
 
 		g_free(comment_pathl);
 		g_free(comment_path);
@@ -122,7 +124,7 @@
 	return success;
 }
 
-gint comment_read(gchar *path, GList **keywords, gchar **comment)
+static gint comment_file_read(gchar *path, GList **keywords, gchar **comment)
 {
 	FILE *f;
 	gchar s_buf[1024];
@@ -184,7 +186,7 @@
 	return TRUE;
 }
 
-gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment)
+static gint comment_legacy_read(FileData *fd, GList **keywords, gchar **comment)
 {
 	gchar *comment_path;
 	gchar *comment_pathl;
@@ -196,7 +198,7 @@
 
 	comment_pathl = path_from_utf8(comment_path);
 
-	success = comment_read(comment_pathl, keywords, comment);
+	success = comment_file_read(comment_pathl, keywords, comment);
 
 	g_free(comment_pathl);
 	g_free(comment_path);
@@ -204,6 +206,100 @@
 	return success;
 }
 
+gchar *comment_key = "Xmp.dc.description";
+gchar *keyword_key = "Xmp.dc.subject";
+
+static gint comment_xmp_read(FileData *fd, GList **keywords, gchar **comment)
+{
+	ExifData *exif = exif_read_fd(fd, FALSE);
+	if (!exif) return FALSE;
+
+	if (comment)
+		{
+		ExifItem *item = exif_get_item(exif, comment_key);
+		*comment = exif_item_get_string(item, 0);
+		}
+	
+	if (keywords)
+		{
+		ExifItem *item = exif_get_item(exif, keyword_key);
+		int count = exif_item_get_elements(item);
+		int i = 0;
+		GList *work = NULL;
+		char *kw = NULL;
+		
+		while (i < count && (kw = exif_item_get_string(item, i++)))
+			{
+			work = g_list_append(work, (gpointer) kw);
+			}
+		
+		*keywords = work;
+		}
+		
+	exif_free(exif);
+	return TRUE;
+}
+
+static gint comment_xmp_write(FileData *fd, GList *keywords, const gchar *comment)
+{
+	gint success = FALSE;
+	GList *work = keywords;
+	ExifData *exif = exif_read_fd(fd, FALSE);
+	if (!exif) return FALSE;
+
+	ExifItem *item = exif_get_item(exif, comment_key);
+	
+	if (item && !(comment && comment[0])) 
+		{
+		exif_item_delete(exif, item); 
+		item = NULL;
+		}
+		
+	if (!item && comment && comment[0]) 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 (work)
+		{
+		item = exif_add_item(exif, keyword_key);
+		
+		while (work)
+			{
+			gchar *kw = (gchar *) work->data;
+			work = work->next;
+		
+			exif_item_set_string(item, kw);
+			}
+		}
+	
+	success = exif_write(exif);
+		
+	exif_free(exif);
+	
+	return success;
+}
+
+gint comment_write(FileData *fd, GList *keywords, const gchar *comment)
+{
+	if (comment_xmp_write(fd, keywords, comment)) return TRUE;
+
+	return comment_legacy_write(fd, keywords, comment);
+}
+
+gint comment_read(FileData *fd, GList **keywords, gchar **comment)
+{
+	if (comment_xmp_read(fd, keywords, comment)) return TRUE;
+
+	return comment_legacy_read(fd, keywords, comment);
+}
+
+
 static gchar *comment_pull(GtkWidget *textview)
 {
 	GtkTextBuffer *buffer;
@@ -290,7 +386,7 @@
 	GList *keywords = NULL;
 	GList *save_list = NULL;
 
-	comment_cache_read(fd, &keywords, &comment);
+	comment_read(fd, &keywords, &comment);
 
 	if (add)
 		{
@@ -323,7 +419,7 @@
 		save_list = list;
 		}
 
-	comment_cache_write(fd, save_list, comment);
+	comment_write(fd, save_list, comment);
 
 	string_list_free(keywords);
 	g_free(comment);
@@ -625,7 +721,7 @@
 	list = keyword_list_pull(bd->keyword_view);
 	comment = comment_pull(bd->comment_view);
 
-	comment_cache_write(bd->fd, list, comment);
+	comment_write(bd->fd, list, comment);
 
 	string_list_free(list);
 	g_free(comment);
@@ -744,7 +840,7 @@
 		gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->fd) ? text_from_time(bd->fd->date) : "");
 		}
 
-	if (comment_cache_read(bd->fd, &keywords, &comment))
+	if (comment_read(bd->fd, &keywords, &comment))
 		{
 		keyword_list_push(bd->keyword_view, keywords);
 		gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)),
--- a/src/bar_info.h	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/bar_info.h	Sun Mar 16 10:32:52 2008 +0000
@@ -27,11 +27,9 @@
 
 void bar_info_maint_renamed(GtkWidget *bar, FileData *fd);
 
-gint comment_write(gchar *path, GList *keywords, const gchar *comment);
-gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment);
+gint comment_write(FileData *fd, GList *keywords, const gchar *comment);
 
-gint comment_read(gchar *path, GList **keywords, gchar **comment);
-gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment);
+gint comment_read(FileData *fd, GList **keywords, gchar **comment);
 
 GList *keyword_list_pull(GtkWidget *text_widget);
 void keyword_list_push(GtkWidget *textview, GList *list);
--- a/src/cache-loader.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/cache-loader.c	Sun Mar 16 10:32:52 2008 +0000
@@ -125,7 +125,7 @@
 		time_t date = -1;
 		ExifData *exif;
 
-		exif = exif_read(cl->fd->path, FALSE);
+		exif = exif_read_fd(cl->fd, FALSE);
 		if (exif)
 			{
 			gchar *text;
--- a/src/exif-common.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/exif-common.c	Sun Mar 16 10:32:52 2008 +0000
@@ -326,3 +326,25 @@
 
 	return NULL;
 }
+
+ExifData *exif_read_fd(FileData *fd, gint parse_color_profile)
+{
+	GList *work = fd->sidecar_files;
+	gchar *sidecar_path = NULL;
+				
+	while(work)
+		{
+		FileData *sfd = work->data;
+		work = work->next;
+		printf("sfd %s\n", sfd->path);
+		if (strcasecmp(sfd->extension, ".xmp") == 0)
+			{
+			sidecar_path = sfd->path;
+			break;
+			}
+		}
+
+
+	// FIXME: some caching would be nice
+	return exif_read(fd->path, sidecar_path, parse_color_profile);
+}
--- a/src/exif.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/exif.c	Sun Mar 16 10:32:52 2008 +0000
@@ -1220,7 +1220,7 @@
 	g_free(exif);
 }
 
-ExifData *exif_read(gchar *path, gint parse_color_profile)
+ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile)
 {
 	ExifData *exif;
 	void *f;
--- a/src/exif.h	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/exif.h	Sun Mar 16 10:32:52 2008 +0000
@@ -105,7 +105,11 @@
  *-----------------------------------------------------------------------------
  */
 
-ExifData *exif_read(gchar *path, gint parse_color_profile);
+ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile);
+
+ExifData *exif_read_fd(FileData *fd, gint parse_color_profile);
+
+
 int exif_write(ExifData *exif);
 void exif_free(ExifData *exif);
 
@@ -132,6 +136,8 @@
 gint exif_item_get_integer(ExifItem *item, gint *value);
 ExifRational *exif_item_get_rational(ExifItem *item, gint *sign);
 
+gchar *exif_item_get_string(ExifItem *item, int idx);
+
 const gchar *exif_get_description_by_key(const gchar *key);
 const gchar *exif_get_tag_description_by_key(const gchar *key);
 
--- a/src/exiv2.cc	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/exiv2.cc	Sun Mar 16 10:32:52 2008 +0000
@@ -28,6 +28,7 @@
 
 extern "C" {
 #include <glib.h> 
+#include "gqview.h"
 #include "exif.h"
 
 }
@@ -35,36 +36,66 @@
 struct _ExifData
 {
 	Exiv2::Image::AutoPtr image;
+	Exiv2::Image::AutoPtr sidecar;
 	Exiv2::ExifData::const_iterator exifIter; /* for exif_get_next_item */
 	Exiv2::IptcData::const_iterator iptcIter; /* for exif_get_next_item */
 	Exiv2::XmpData::const_iterator xmpIter; /* for exif_get_next_item */
+	bool have_sidecar;
 
-	_ExifData(gchar *path, gint parse_color_profile)
+
+	_ExifData(gchar *path, gchar *sidecar_path, gint parse_color_profile)
 	{
+		have_sidecar = false;
 		image = Exiv2::ImageFactory::open(path);
 //		g_assert (image.get() != 0);
 		image->readMetadata();
+		
+		printf("xmp count %d\n", image->xmpData().count());
+		if (sidecar_path && image->xmpData().empty())
+			{
+			sidecar = Exiv2::ImageFactory::open(sidecar_path);
+			sidecar->readMetadata();
+			have_sidecar = sidecar->good();
+			printf("sidecar xmp count %d\n", sidecar->xmpData().count());
+			}
+		
 	}
 	
 	void writeMetadata()
 	{
+		if (have_sidecar) sidecar->writeMetadata();
 		image->writeMetadata();
 	}
 	
+	Exiv2::ExifData &exifData ()
+	{
+		return image->exifData();
+	}
+
+	Exiv2::IptcData &iptcData ()
+	{
+		return image->iptcData();
+	}
+
+	Exiv2::XmpData &xmpData ()
+	{
+		return have_sidecar ? sidecar->xmpData() : image->xmpData();
+	}
+	
 
 };
 
 extern "C" {
 
-ExifData *exif_read(gchar *path, gint parse_color_profile)
+ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile)
 {
-	printf("exif %s\n", path);
+	printf("exif %s %s\n", path, sidecar_path ? sidecar_path : "-");
 	try {
-		return new ExifData(path, parse_color_profile);
+		return new ExifData(path, sidecar_path, parse_color_profile);
 	}
 	catch (Exiv2::AnyError& e) {
 		std::cout << "Caught Exiv2 exception '" << e << "'\n";
-		return 0;
+		return NULL;
 	}
 	
 }
@@ -95,21 +126,21 @@
 		Exiv2::Metadatum *item;
 		try {
 			Exiv2::ExifKey ekey(key);
-			Exiv2::ExifData::iterator pos = exif->image->exifData().findKey(ekey);
-			if (pos == exif->image->exifData().end()) return NULL;
+			Exiv2::ExifData::iterator pos = exif->exifData().findKey(ekey);
+			if (pos == exif->exifData().end()) return NULL;
 			item = &*pos;
 		}
 		catch (Exiv2::AnyError& e) {
 			try {
 				Exiv2::IptcKey ekey(key);
-				Exiv2::IptcData::iterator pos = exif->image->iptcData().findKey(ekey);
-				if (pos == exif->image->iptcData().end()) return NULL;
+				Exiv2::IptcData::iterator pos = exif->iptcData().findKey(ekey);
+				if (pos == exif->iptcData().end()) return NULL;
 				item = &*pos;
 			}
 			catch (Exiv2::AnyError& e) {
 				Exiv2::XmpKey ekey(key);
-				Exiv2::XmpData::iterator pos = exif->image->xmpData().findKey(ekey);
-				if (pos == exif->image->xmpData().end()) return NULL;
+				Exiv2::XmpData::iterator pos = exif->xmpData().findKey(ekey);
+				if (pos == exif->xmpData().end()) return NULL;
 				item = &*pos;
 			}
 		}
@@ -127,23 +158,23 @@
 		Exiv2::Metadatum *item;
 		try {
 			Exiv2::ExifKey ekey(key);
-			exif->image->exifData().add(ekey, NULL);
-			Exiv2::ExifData::iterator pos = exif->image->exifData().end(); // a hack, there should be a better way to get the currently added item
+			exif->exifData().add(ekey, NULL);
+			Exiv2::ExifData::iterator pos = exif->exifData().end(); // a hack, there should be a better way to get the currently added item
 			pos--;
 			item = &*pos;
 		}
 		catch (Exiv2::AnyError& e) {
 			try {
 				Exiv2::IptcKey ekey(key);
-				exif->image->iptcData().add(ekey, NULL);
-				Exiv2::IptcData::iterator pos = exif->image->iptcData().end();
+				exif->iptcData().add(ekey, NULL);
+				Exiv2::IptcData::iterator pos = exif->iptcData().end();
 				pos--;
 				item = &*pos;
 			}
 			catch (Exiv2::AnyError& e) {
 				Exiv2::XmpKey ekey(key);
-				exif->image->xmpData().add(ekey, NULL);
-				Exiv2::XmpData::iterator pos = exif->image->xmpData().end();
+				exif->xmpData().add(ekey, NULL);
+				Exiv2::XmpData::iterator pos = exif->xmpData().end();
 				pos--;
 				item = &*pos;
 			}
@@ -160,22 +191,22 @@
 ExifItem *exif_get_first_item(ExifData *exif)
 {
 	try {
-		exif->exifIter = exif->image->exifData().begin();
-		exif->iptcIter = exif->image->iptcData().begin();
-		exif->xmpIter = exif->image->xmpData().begin();
-		if (exif->exifIter != exif->image->exifData().end()) 
+		exif->exifIter = exif->exifData().begin();
+		exif->iptcIter = exif->iptcData().begin();
+		exif->xmpIter = exif->xmpData().begin();
+		if (exif->exifIter != exif->exifData().end()) 
 			{
 			const Exiv2::Metadatum *item = &*exif->exifIter;
 			exif->exifIter++;
 			return (ExifItem *)item;
 			}
-		if (exif->iptcIter != exif->image->iptcData().end()) 
+		if (exif->iptcIter != exif->iptcData().end()) 
 			{
 			const Exiv2::Metadatum *item = &*exif->iptcIter;
 			exif->iptcIter++;
 			return (ExifItem *)item;
 			}
-		if (exif->xmpIter != exif->image->xmpData().end()) 
+		if (exif->xmpIter != exif->xmpData().end()) 
 			{
 			const Exiv2::Metadatum *item = &*exif->xmpIter;
 			exif->xmpIter++;
@@ -193,19 +224,19 @@
 ExifItem *exif_get_next_item(ExifData *exif)
 {
 	try {
-		if (exif->exifIter != exif->image->exifData().end())
+		if (exif->exifIter != exif->exifData().end())
 			{
 			const Exiv2::Metadatum *item = &*exif->exifIter;
 			exif->exifIter++;
 			return (ExifItem *)item;
 		}
-		if (exif->iptcIter != exif->image->iptcData().end())
+		if (exif->iptcIter != exif->iptcData().end())
 			{
 			const Exiv2::Metadatum *item = &*exif->iptcIter;
 			exif->iptcIter++;
 			return (ExifItem *)item;
 		}
-		if (exif->xmpIter != exif->image->xmpData().end())
+		if (exif->xmpIter != exif->xmpData().end())
 			{
 			const Exiv2::Metadatum *item = &*exif->xmpIter;
 			exif->xmpIter++;
@@ -345,6 +376,26 @@
 	}
 }
 
+gchar *exif_item_get_string(ExifItem *item, int idx)
+{
+	try {
+		if (!item) return NULL;
+		Exiv2::Metadatum *em = (Exiv2::Metadatum *)item;
+		std::string str = em->toString(idx);
+		if (idx == 0 && str == "") str = em->toString();
+		if (str.length() > 5 && str.substr(0, 5) == "lang=") 
+			{
+        		std::string::size_type pos = str.find_first_of(' ');
+        		if (pos != std::string::npos) str = str.substr(pos+1);
+			}
+
+		return g_strdup(str.c_str());
+	}
+	catch (Exiv2::AnyError& e) {
+		return NULL;
+	}
+}
+
 
 gint exif_item_get_integer(ExifItem *item, gint *value)
 {
@@ -403,21 +454,21 @@
 {
 	try {
 		if (!item) return 0;
-		for (Exiv2::ExifData::iterator i = exif->image->exifData().begin(); i != exif->image->exifData().end(); ++i) {
+		for (Exiv2::ExifData::iterator i = exif->exifData().begin(); i != exif->exifData().end(); ++i) {
 			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->image->exifData().erase(i);
+				i = exif->exifData().erase(i);
 				return 1;
 			}
 		}
-		for (Exiv2::IptcData::iterator i = exif->image->iptcData().begin(); i != exif->image->iptcData().end(); ++i) {
+		for (Exiv2::IptcData::iterator i = exif->iptcData().begin(); i != exif->iptcData().end(); ++i) {
 			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->image->iptcData().erase(i);
+				i = exif->iptcData().erase(i);
 				return 1;
 			}
 		}
-		for (Exiv2::XmpData::iterator i = exif->image->xmpData().begin(); i != exif->image->xmpData().end(); ++i) {
+		for (Exiv2::XmpData::iterator i = exif->xmpData().begin(); i != exif->xmpData().end(); ++i) {
 			if (((Exiv2::Metadatum *)item) == &*i) {
-				i = exif->image->xmpData().erase(i);
+				i = exif->xmpData().erase(i);
 				return 1;
 			}
 		}
--- a/src/filelist.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/filelist.c	Sun Mar 16 10:32:52 2008 +0000
@@ -209,6 +209,7 @@
 	filter_add_if_missing("ico", "Icon file", ".ico;.cur", FALSE);
 	filter_add_if_missing("ras", "Raster", ".ras", FALSE);
 	filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FALSE);
+	filter_add_if_missing("xmp", "XMP sidecar", ".xmp", FALSE);
 
 	/* These are the raw camera formats with embedded jpeg/exif.
 	 * (see format_raw.c)
@@ -467,7 +468,7 @@
 
 void sidecar_ext_add_defaults()
 {
-	sidecar_ext_parse(".jpg;.cr2;.nef;.crw", FALSE);
+	sidecar_ext_parse(".jpg;.cr2;.nef;.crw;.xmp", FALSE);
 }
 
 /*
--- a/src/image.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/image.c	Sun Mar 16 10:32:52 2008 +0000
@@ -425,7 +425,7 @@
 	if (exif_rotate_enable ||
 	    (imd->color_profile_enable && imd->color_profile_use_image) )
 		{
-		exif = exif_read(imd->image_fd->path, (imd->color_profile_enable && imd->color_profile_use_image));
+		exif = exif_read_fd(imd->image_fd, (imd->color_profile_enable && imd->color_profile_use_image));
 		}
 
 	if (exif_rotate_enable && exif)
@@ -624,7 +624,7 @@
 			{
 			ExifData *exif = NULL;
 
-			if (imd->color_profile_use_image) exif = exif_read(imd->image_fd->path, TRUE);
+			if (imd->color_profile_use_image) exif = exif_read_fd(imd->image_fd, TRUE);
 			image_post_process_color(imd, imd->prev_color_row, exif);
 			exif_free(exif);
 			}
--- a/src/pan-view.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/pan-view.c	Sun Mar 16 10:32:52 2008 +0000
@@ -1434,7 +1434,7 @@
 	gint i;
 
 	if (!fd) return;
-	exif = exif_read(fd->path, FALSE);
+	exif = exif_read_fd(fd, FALSE);
 	if (!exif) return;
 
 	pan_text_alignment_add(ta, NULL, NULL);
--- a/src/search.c	Sat Mar 15 19:53:33 2008 +0000
+++ b/src/search.c	Sun Mar 16 10:32:52 2008 +0000
@@ -1772,7 +1772,7 @@
 		tested = TRUE;
 		match = FALSE;
 
-		if (comment_cache_read(fd, &list, NULL))
+		if (comment_read(fd, &list, NULL))
 			{
 			GList *needle;
 			GList *haystack;