prepared infrastructure for delayed metadata writting - refreshing
authorVladimir Nadvornik <nadvornik@suse.cz>
Mon, 15 Dec 2008 22:47:31 +0000 (22:47 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Mon, 15 Dec 2008 22:47:31 +0000 (22:47 +0000)
metadata immediately before writting is now possible

modified metadata are stored in fd->modified_xmp

src/exif-common.c
src/exif.c
src/exif.h
src/exiv2.cc
src/metadata.c
src/typedefs.h

index 1aba8ba..81c7d06 100644 (file)
@@ -627,10 +627,27 @@ ExifData *exif_read_fd(FileData *fd)
                        }
                }
 
-       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;
index 2923085..35781b0 100644 (file)
@@ -1209,7 +1209,7 @@ void exif_free(ExifData *exif)
        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 @@ gint exif_write(ExifData *exif)
        return 0;
 }
 
-ExifItem *exif_add_item(ExifData *exif, const gchar *key)
-{
-       return NULL;
-}
-
-gint exif_item_delete(ExifData *exif, ExifItem *item)
-{
-       return 0;
-}
 
-gint exif_item_set_string(ExifItem *item, const gchar *str)
+gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values)
 {
        return 0;
 }
 
-
 typedef struct _UnmapData UnmapData;
 struct _UnmapData
 {
index 5ed08a9..e9c3c5a 100644 (file)
@@ -107,10 +107,11 @@ struct _ExifFormattedText
  *-----------------------------------------------------------------------------
  */
 
-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 @@ gint exif_get_integer(ExifData *exif, const gchar *key, gint *value);
 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_tag_description_by_key(const gchar *key);
 
 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);
 
index 31bf976..ea05e30 100644 (file)
@@ -201,6 +201,10 @@ public:
        }
 };
 
+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 @@ protected:
 #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 @@ public:
 #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 @@ public:
 
 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,49 +744,71 @@ gchar *exif_get_tag_description_by_key(const gchar *key)
        }
 }
 
-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));
-               return 1;
-               }
-       catch (Exiv2::AnyError& e) {
-               return 0;
-       }
-}
+               const GList *work = values;
 
-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;
-                       }
+               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;
+                               }
                }
-               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;
+               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)
-               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;
+                               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
                        }
                }
-#endif
-               return 0;
+               return 1;
        }
        catch (Exiv2::AnyError& e) {
+               std::cout << "Caught Exiv2 exception '" << e << "'\n";
                return 0;
        }
 }
 
+
 void exif_add_jpeg_color_profile(ExifData *exif, unsigned char *cp_data, guint cp_length)
 {
        exif->add_jpeg_color_profile(cp_data, cp_length);
index 29378b1..1c0949c 100644 (file)
@@ -30,6 +30,26 @@ typedef enum {
 } 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_read(FileData *fd, GList **keywords, gchar **comment)
 
 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);
-
-               work = keywords;
-               while (work)
-                       {
-                       exif_item_set_string(item, (gchar *) work->data);
-                       work = work->next;
-                       }
-               }
+       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));
 
-       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;
 }
index 2b5533e..9a43c9f 100644 (file)
@@ -440,6 +440,7 @@ struct _FileData {
        gint exif_orientation;
        
        ExifData *exif;
+       GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values
 };
 
 struct _LayoutWindow