[PATCH] New sample "editxmp": edit XMP metadata in an external editor
Andrew Cady
d at jerkface.net
Sun Jan 24 22:25:04 PST 2010
This is a new command for the samples directory that is somewhat useful
as an application. It uses a common unixy technique to allow the user
to edit XMP metadata: it reads the XMP metadata from a file, saves the
metadata as text to a temporary file, and launches a text editor on the
temporary file; if the user saves it, then the metadata is written back
into the original file. As an example, it shows the whole cycle an
editor must use, and could serve as a starting point for an XMP editor
that was a little less brain-dead about the meaning of XMP data.
---
.gitignore | 1 +
samples/source/EditXMP.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++
samples/source/Makefile.am | 4 ++
3 files changed, 105 insertions(+), 0 deletions(-)
create mode 100644 samples/source/EditXMP.cpp
diff --git a/.gitignore b/.gitignore
index 851d0e8..5618caa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,4 @@ samples/source/customschema
samples/source/modifyingxmp
samples/source/readingxmp
samples/source/xmpcoverageLog.txt
+samples/source/editxmp
diff --git a/samples/source/EditXMP.cpp b/samples/source/EditXMP.cpp
new file mode 100644
index 0000000..52b9dfd
--- /dev/null
+++ b/samples/source/EditXMP.cpp
@@ -0,0 +1,100 @@
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <errno.h>
+#include <error.h>
+#include <string>
+
+#define TXMP_STRING_TYPE std::string
+#define XMP_INCLUDE_XMPFILES 1
+#include "XMP.hpp"
+#include "XMP.incl_cpp"
+
+using namespace std;
+
+int externally_edit_string(string s)
+// returns fd of file containing edited string
+{
+ char *tmpdir = getenv("TMPDIR");
+ if (!tmpdir) tmpdir = P_tmpdir;
+ char *tmp_template = "/tmpedit.XXXXXX";
+
+ char *tmpfile =
+ (char *) malloc(strlen(tmpdir) + strlen(tmp_template) + 1);
+ strcpy(tmpfile, tmpdir);
+ strcat(tmpfile, tmp_template);
+
+ int fd;
+ if ((fd = mkstemp(tmpfile)) < 0)
+ error(-1, errno, "mkstemp() error");
+ if (write(fd, s.c_str(), s.length()) < 0)
+ error(-1, errno, "write() error");
+ if (fsync(fd) < 0)
+ error(-1, errno, "fsync() error");
+
+ char *editor = getenv("VISUAL");
+ if (!editor) editor = getenv("EDITOR");
+ if (!editor) editor = "vi";
+ string cmd = string(editor) + " " + tmpfile;
+
+ int ret = system(cmd.c_str());
+ if (ret)
+ error(-1, ret < 0 ? errno : 0, "system() error");
+
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ error(-1, errno, "lseek() error");
+
+ return fd;
+}
+
+extern "C"
+int main (int argc, const char *argv[])
+{
+ if (argc != 2) {
+ printf("usage: %s <file>\n", program_invocation_name);
+ puts( "Environment variables VISUAL and EDITOR are used "
+ "to determine the text editor; 'vi' is the default." );
+ return 0;
+ }
+ const char *filename = argv[1];
+
+ // initialize XMP
+ if (!SXMPMeta::Initialize())
+ error(-1, 0, "SXMPMeta::Initialize() error");
+ if (!SXMPFiles::Initialize())
+ error(-1, 0, "SXMPFiles::Initialize() error" );
+
+ SXMPMeta xmpMeta;
+ SXMPFiles xmpFile;
+ XMP_PacketInfo xmpPacket;
+
+ xmpFile.OpenFile(filename, kXMP_UnknownFile,
+ kXMPFiles_OpenForUpdate|kXMPFiles_OpenOnlyXMP);
+ if (!xmpFile.GetXMP (&xmpMeta, 0, &xmpPacket))
+ error(-1, 0, "xmpFile.GetXMP() error. "
+ "There may be no XMP metadata in this file.");
+
+ // read the meta-data
+ string s;
+ xmpMeta.SerializeToBuffer(&s,
+ kXMP_OmitPacketWrapper|kXMP_UseCompactFormat);
+
+ // edit and write the meta-data
+ int fd;
+ if (fd = externally_edit_string(s)) {
+ char buf[1024*8];
+ ssize_t n;
+ while (n = read(fd, buf, sizeof(buf))) {
+ if (n < 0) error(-1, errno, "read() error");
+ xmpMeta.ParseFromBuffer(buf, n, kXMP_ParseMoreBuffers);
+ }
+ xmpMeta.ParseFromBuffer(buf, 0, 0);
+ xmpFile.PutXMP(xmpMeta);
+ }
+
+ // cleanup XMP
+ xmpFile.CloseFile();
+ SXMPFiles::Terminate();
+ SXMPMeta::Terminate();
+ return 0;
+}
diff --git a/samples/source/Makefile.am b/samples/source/Makefile.am
index 1715096..443b2dd 100644
--- a/samples/source/Makefile.am
+++ b/samples/source/Makefile.am
@@ -39,6 +39,7 @@ noinst_PROGRAMS = xmpcoverage xmpfilescoverage dumpxmp dumpmainxmp\
customschema \
modifyingxmp \
readingxmp \
+ editxmp \
$(NULL)
AM_CXXFLAGS = -fexceptions -funsigned-char -fPIC \
@@ -74,3 +75,6 @@ dumpxmp_LDADD = $(XMPLIBS)
dumpmainxmp_SOURCES = DumpMainXMP.cpp
dumpmainxmp_LDADD = $(XMPLIBS)
+
+editxmp_SOURCES = EditXMP.cpp
+editxmp_LDADD = $(XMPLIBS)
--
1.5.6.5
More information about the Exempi-devel
mailing list