# HG changeset patch # User nadvornik # Date 1229381251 0 # Node ID 43bfcbb62cd6dba9e015ffdf0457a03009d27127 # Parent 8bf3fff49dddac1a8f542ad81c3f8460511e8302 prepared infrastructure for delayed metadata writting - refreshing metadata immediately before writting is now possible modified metadata are stored in fd->modified_xmp diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/exif-common.c --- 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; diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/exif.c --- 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 { diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/exif.h --- 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); diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/exiv2.cc --- 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) { diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/metadata.c --- 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; } diff -r 8bf3fff49ddd -r 43bfcbb62cd6 src/typedefs.h --- 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