[tracker/coalesce] Change structure of the JPEG extractor



commit fd1912d1cf7ee542c76323040e567b06c2292290
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Sep 2 17:31:51 2009 +0200

    Change structure of the JPEG extractor
    
    - This breaks the TIFF, XMP, PDF and GStreamer extractor
    - This is a work in progress
    - Currently this doesn't add any of the tags of JPEG to the
      SPARQL update query (they just all get freed atm)
    - This cleans up the shared XMP, Exif and IPTC code
    
    This commit is going to be squashed together with a few other
    commits. This means that you should not rely your work on this
    branch on Philip not going to git-rebase it. He will.
    
    Guaranteed.

 src/tracker-extract/Makefile.am            |    9 +-
 src/tracker-extract/tracker-exif.c         |  452 ++++++++++++++++++++++++++
 src/tracker-extract/tracker-exif.h         |   40 +++
 src/tracker-extract/tracker-extract-jpeg.c |  480 ++++++++--------------------
 src/tracker-extract/tracker-iptc.c         |  116 +++----
 src/tracker-extract/tracker-iptc.h         |   31 ++-
 src/tracker-extract/tracker-xmp.c          |  262 +++++-----------
 src/tracker-extract/tracker-xmp.h          |   23 ++-
 8 files changed, 819 insertions(+), 594 deletions(-)
---
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index 8c68c3c..5e6f457 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -100,6 +100,11 @@ xmp_sources = 								\
 	tracker-xmp.c							\
 	tracker-xmp.h
 
+# Common exif Sources
+exif_sources =								\
+	tracker-exif.c							\
+	tracker-exif.h
+
 # Common iptc Sources
 iptc_sources =								\
 	tracker-iptc.c							\
@@ -202,7 +207,7 @@ libextract_xine_la_LIBADD = $(GLIB2_LIBS) $(XINE_LIBS) $(GCOV_LIBS) \
 	$(top_builddir)/src/libtracker-common/libtracker-common.la
 
 # JPEG
-libextract_jpeg_la_SOURCES = tracker-extract-jpeg.c $(xmp_sources) $(iptc_sources)
+libextract_jpeg_la_SOURCES = tracker-extract-jpeg.c $(xmp_sources) $(iptc_sources) $(exif_sources)
 libextract_jpeg_la_LDFLAGS = $(module_flags)
 libextract_jpeg_la_LIBADD = $(GLIB2_LIBS) $(LIBJPEG_LIBS) $(LIBEXIF_LIBS) $(LIBIPTCDATA_LIBS) $(EXEMPI_LIBS) $(GCOV_LIBS) \
 	$(top_builddir)/src/libtracker-common/libtracker-common.la
@@ -286,4 +291,4 @@ BUILT_SOURCES = 							\
 
 CLEANFILES = $(BUILT_SOURCES)
 
-EXTRA_DIST = tracker-marshal.list
\ No newline at end of file
+EXTRA_DIST = tracker-marshal.list
diff --git a/src/tracker-extract/tracker-exif.c b/src/tracker-extract/tracker-exif.c
new file mode 100644
index 0000000..a7ba24f
--- /dev/null
+++ b/src/tracker-extract/tracker-exif.c
@@ -0,0 +1,452 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Tracker Exif - Exif helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#include "config.h"
+
+#include <locale.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+
+#include "tracker-main.h"
+#include "tracker-exif.h"
+
+#include <libtracker-common/tracker-type-utils.h>
+#include <libtracker-common/tracker-utils.h>
+
+
+#ifdef HAVE_LIBEXIF
+
+#include <libexif/exif-data.h>
+
+#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S"
+
+#ifndef HAVE_STRCASESTR
+static gchar *
+strcasestr (const gchar *haystack, 
+	    const gchar *needle)
+{
+	gchar *p;
+	gchar *startn = NULL;
+	gchar *np = NULL;
+
+	for (p = (gchar *) haystack; *p; p++) {
+		if (np) {
+			if (toupper (*p) == toupper (*np)) {
+				if (!*++np) {
+					return startn;
+				}
+			} else {
+				np = 0;
+			}
+		} else if (toupper (*p) == toupper (*needle)) {
+			np = (gchar *) needle + 1;
+			startn = p;
+		}
+	}
+
+	return NULL;
+}
+#endif /* HAVE_STRCASESTR */
+
+static gchar *
+get_date (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+		/* From: ex; date "2007:04:15 15:35:58"
+		 * To  : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime */
+		return tracker_date_format_to_iso8601 (buf, EXIF_DATE_FORMAT);
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_focal_length(ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+		exif_entry_get_value (entry, buf, 1024);
+		return g_strndup (buf, strstr (buf, " mm") - buf);
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_flash (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "flash fired")) {
+			return g_strdup ("nmm:flash-on");
+		}
+
+		return g_strdup ("nmm:flash-off");
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_fnumber (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+		gchar *new_fn;
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strlen (buf) <= 0) {
+			return NULL;
+		}
+
+		new_fn = g_strdup (buf);
+
+		if (new_fn[0] == 'F') {
+			new_fn[0] = ' ';
+		} else if (buf[0] == 'f' && new_fn[1] == '/') {
+			new_fn[0] = new_fn[1] = ' ';
+		}
+
+		return g_strstrip (new_fn);
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_exposure_time (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+		gchar *sep;
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		sep = strchr (buf, '/');
+
+		if (sep) {
+			gdouble fraction;
+
+			fraction = g_ascii_strtod (sep + 1, NULL);
+
+			if (fraction > 0.0) {
+				gdouble val;
+				gchar   bufr[G_ASCII_DTOSTR_BUF_SIZE];
+
+				val = 1.0f / fraction;
+				g_ascii_dtostr (bufr, sizeof(bufr), val);
+
+				return g_strdup (bufr);
+			}
+		}
+
+		return g_strdup (buf);
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_orientation (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+	guint i;
+
+	if (entry) {
+		gchar buf[1024];
+		static const gchar *ostr[8] = {
+			/* 0 */ "top - left",
+			/* 1 */ "top - right",
+			/* 2 */ "bottom - right",
+			/* 3 */ "bottom - left",
+			/* 4 */ "left - top",
+			/* 5 */ "right - top",
+			/* 6 */ "right - bottom",
+			/* 7 */ "left - bottom"
+		};
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		for (i=0; i < 8; i++) {
+			if (g_strcmp0 (buf, ostr[i]) == 0) {
+				switch (i) {
+					case 0:
+					return g_strdup ("nfo:orientation-top");
+					case 1:
+					return g_strdup ("nfo:orientation-top-mirror");
+					case 2:
+					return g_strdup ("nfo:orientation-bottom");
+					case 3:
+					return g_strdup ("nfo:orientation-bottom-mirror");
+					case 4:
+					return g_strdup ("nfo:orientation-left-mirror");
+					case 5:
+					return g_strdup ("nfo:orientation-right");
+					case 6:
+					return g_strdup ("nfo:orientation-right-mirror");
+					case 7:
+					return g_strdup ("nfo:orientation-left");
+					default:
+					break;
+				}
+			}
+		}
+
+		return g_strdup ("nfo:orientation-top");
+
+	}
+
+	return NULL;
+}
+
+
+static gchar *
+get_metering_mode (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "center")) {
+			return g_strdup ("nmm:meteringMode-center-weighted-average");
+		}
+
+		if (strcasestr (buf, "average")) {
+			return g_strdup ("nmm:meteringMode-average");
+		}
+
+		if (strcasestr (buf, "spot")) {
+			return g_strdup ("nmm:meteringMode-spot");
+		}
+
+		if (strcasestr (buf, "multispot")) {
+			return g_strdup ("nmm:meteringMode-multispot");
+		}
+
+		if (strcasestr (buf, "pattern")) {
+			return g_strdup ("nmm:meteringMode-pattern");
+		}
+
+		if (strcasestr (buf, "partial")) {
+			return g_strdup ("nmm:meteringMode-partial");
+		}
+
+		return g_strdup ("nmm:meteringMode-other");
+	}
+
+	return NULL;
+}
+
+
+static gchar *
+get_white_balance (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+		exif_entry_get_value (entry, buf, 1024);
+
+		if (strcasestr (buf, "auto")) {
+			return g_strdup ("nmm:whiteBalance-auto");
+		}
+
+		/* Found in the field: sunny, fluorescent, incandescent, cloudy.
+		 * These will this way also yield as manual. */
+
+		return g_strdup ("nmm:whiteBalance-manual");
+	}
+
+	return NULL;
+}
+
+static gchar *
+get_value (ExifData *exif, ExifTag tag)
+{
+	ExifEntry *entry = exif_data_get_entry (exif, tag);
+
+	if (entry) {
+		gchar buf[1024];
+
+		exif_entry_get_value (entry, buf, 1024);
+
+		return g_strdup (buf);
+	}
+
+	return NULL;
+}
+
+#endif /* HAVE_LIBEXIF */
+
+void
+tracker_read_exif (const unsigned char *buffer,
+                   size_t		len,
+                   const gchar         *uri,
+                   TrackerExifData     *data)
+{
+#ifdef HAVE_LIBEXIF
+	guint i;
+	ExifData *exif;
+	ExifTag p[20] = { EXIF_TAG_PIXEL_Y_DIMENSION, 
+	        /* 01 */  EXIF_TAG_PIXEL_X_DIMENSION,
+	        /* 02 */  EXIF_TAG_RELATED_IMAGE_WIDTH,
+	        /* 03 */  EXIF_TAG_DOCUMENT_NAME, 
+	        /* 04 */  EXIF_TAG_DATE_TIME,
+	        /* 05 */  EXIF_TAG_DATE_TIME_ORIGINAL, 
+	        /* 06 */  EXIF_TAG_ARTIST,
+	        /* 07 */  EXIF_TAG_USER_COMMENT, 
+	        /* 08 */  EXIF_TAG_IMAGE_DESCRIPTION,
+	        /* 09 */  EXIF_TAG_MAKE, 
+	        /* 10 */  EXIF_TAG_ORIENTATION,
+	        /* 11 */  EXIF_TAG_EXPOSURE_TIME,
+	        /* 12 */  EXIF_TAG_FNUMBER, 
+	        /* 13 */  EXIF_TAG_FLASH, 
+	        /* 14 */  EXIF_TAG_FOCAL_LENGTH, 
+	        /* 15 */  EXIF_TAG_ISO_SPEED_RATINGS,
+	        /* 16 */  EXIF_TAG_METERING_MODE,
+	        /* 17 */  EXIF_TAG_WHITE_BALANCE, 
+	        /* 18 */  EXIF_TAG_COPYRIGHT,
+		/* 19 */  EXIF_TAG_MODEL };
+
+	exif = exif_data_new();
+
+	exif_data_set_option (exif, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
+	exif_data_unset_option (exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+	exif_data_set_option (exif, EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE);
+
+	exif_data_load_data (exif, (unsigned char *) buffer, len);
+
+	for (i = 0 ; i < 20; i++) {
+		switch (p[i]) {
+			case EXIF_TAG_PIXEL_Y_DIMENSION:
+				if (!data->y_dimention)
+					data->y_dimention = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_PIXEL_X_DIMENSION:
+				if (!data->x_dimention)
+					data->x_dimention = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_RELATED_IMAGE_WIDTH:
+				if (!data->image_width)
+					data->image_width = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_DOCUMENT_NAME:
+				if (!data->document_name)
+					data->document_name = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_DATE_TIME:
+				if (!data->time) {
+					data->time = get_date (exif, p[1]);
+				}
+				break;
+			case EXIF_TAG_DATE_TIME_ORIGINAL:
+				if (!data->time_original)
+					data->time_original = get_date (exif, p[i]);
+				break;
+			case EXIF_TAG_ARTIST:
+				if (!data->artist)
+					data->artist = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_USER_COMMENT:
+				if (!data->user_comment)
+					data->user_comment = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_IMAGE_DESCRIPTION:
+				if (!data->description)
+					data->description = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_MAKE:
+				if (!data->make)
+					data->make = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_MODEL:
+				if (!data->model)
+					data->model = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_ORIENTATION:
+				if (!data->orientation)
+					data->orientation = get_orientation (exif, p[i]);
+				break;
+			case EXIF_TAG_EXPOSURE_TIME:
+				if (!data->exposure_time)
+					data->exposure_time = get_exposure_time (exif, p[i]);
+				break;
+			case EXIF_TAG_FNUMBER:
+				if (!data->fnumber)
+					data->fnumber = get_fnumber (exif, p[i]);
+				break;
+			case EXIF_TAG_FLASH:
+				if (!data->flash)
+					data->flash = get_flash (exif, p[i]);
+				break;
+			case EXIF_TAG_FOCAL_LENGTH:
+				if (!data->focal_length)
+					data->focal_length = get_focal_length (exif, p[i]);
+				break;
+			case EXIF_TAG_ISO_SPEED_RATINGS:
+				if (!data->iso_speed_ratings)
+					data->iso_speed_ratings = get_value (exif, p[i]);
+				break;
+			case EXIF_TAG_METERING_MODE:
+				if (!data->metering_mode)
+					data->metering_mode = get_metering_mode (exif, p[i]);
+				break;
+			case EXIF_TAG_WHITE_BALANCE:
+				if (!data->white_balance)
+					data->white_balance = get_white_balance (exif, p[i]);
+				break;
+			case EXIF_TAG_COPYRIGHT:
+				if (!data->copyright)
+					data->copyright = get_value (exif, p[i]);
+				break;
+			default:
+				break;
+		}
+	
+	}
+
+	exif_data_free (exif);
+
+#endif /* HAVE_LIBEXIF */
+}
+
diff --git a/src/tracker-extract/tracker-exif.h b/src/tracker-extract/tracker-exif.h
new file mode 100644
index 0000000..ccedc31
--- /dev/null
+++ b/src/tracker-extract/tracker-exif.h
@@ -0,0 +1,40 @@
+/* Tracker Xmp - Xmp helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef _TRACKER_EXIF_H_
+#define _TRACKER_EXIF_H_
+
+#include <glib.h>
+
+typedef struct {
+	gchar *y_dimention, *x_dimention, *image_width, *document_name, *time, *time_original,
+	      *artist, *user_comment, *description, *make, *model, *orientation,
+	      *exposure_time, *fnumber, *flash, *focal_length, *iso_speed_ratings,
+	      *metering_mode, *white_balance, *copyright;
+} TrackerExifData;
+
+void tracker_read_exif (const unsigned char *buffer,
+                        size_t               len,
+                        const gchar         *uri,
+                        TrackerExifData     *data);
+
+#endif /* _TRACKER_EXIF_H_ */
+
diff --git a/src/tracker-extract/tracker-extract-jpeg.c b/src/tracker-extract/tracker-extract-jpeg.c
index 725abaa..6dcb63c 100644
--- a/src/tracker-extract/tracker-extract-jpeg.c
+++ b/src/tracker-extract/tracker-extract-jpeg.c
@@ -54,32 +54,38 @@
 #include "tracker-main.h"
 #include "tracker-xmp.h"
 #include "tracker-iptc.h"
+#include "tracker-exif.h"
 
+#define RDF_PREFIX TRACKER_RDF_PREFIX
 #define NMM_PREFIX TRACKER_NMM_PREFIX
 #define NFO_PREFIX TRACKER_NFO_PREFIX
 #define NIE_PREFIX TRACKER_NIE_PREFIX
 #define DC_PREFIX TRACKER_DC_PREFIX
 #define NCO_PREFIX TRACKER_NCO_PREFIX
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
+#ifdef HAVE_LIBEXIF
+#define EXIF_NAMESPACE		"Exif"
+#define EXIF_NAMESPACE_LENGTH	4
+#endif /* HAVE_LIBEXIF */
 
 #ifdef HAVE_EXEMPI
-#define XMP_NAMESPACE	     "http://ns.adobe.com/xap/1.0/\x00";
-#define XMP_NAMESPACE_LENGTH 29
+#define XMP_NAMESPACE		"http://ns.adobe.com/xap/1.0/\x00";
+#define XMP_NAMESPACE_LENGTH	29
 #endif /* HAVE_EXEMPI */
 
-#ifdef HAVE_LIBEXIF
-#include <libexif/exif-data.h>
-#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S"
-#endif /* HAVE_LIBEXIF */
-
 #ifdef HAVE_LIBIPTCDATA
-#define PS3_NAMESPACE	     "Photoshop 3.0\0"
-#define PS3_NAMESPACE_LENGTH 14
+#define PS3_NAMESPACE		"Photoshop 3.0\0"
+#define PS3_NAMESPACE_LENGTH	14
 #include <libiptcdata/iptc-jpeg.h>
 #endif /* HAVE_LIBIPTCDATA */
 
+typedef struct {
+	gchar *camera, *title, *orientation, *copyright, *white_balance, 
+	      *fnumber, *flash, *focal_length, *time_original, *artist, 
+	      *exposure_time, *iso_speed_ratings, *date, *description,
+	      *metering_mode;
+} JpegNeedsMergeData;
+
 static void extract_jpeg (const gchar *filename,
 			  TrackerSparqlBuilder   *metadata);
 
@@ -88,37 +94,6 @@ static TrackerExtractData data[] = {
 	{ NULL, NULL }
 };
 
-
-#ifndef HAVE_STRCASESTR
-
-static gchar *
-strcasestr (const gchar *haystack, 
-	    const gchar *needle)
-{
-	gchar *p;
-	gchar *startn = NULL;
-	gchar *np = NULL;
-
-	for (p = (gchar *) haystack; *p; p++) {
-		if (np) {
-			if (toupper (*p) == toupper (*np)) {
-				if (!*++np) {
-					return startn;
-				}
-			} else {
-				np = 0;
-			}
-		} else if (toupper (*p) == toupper (*needle)) {
-			np = (gchar *) needle + 1;
-			startn = p;
-		}
-	}
-
-	return NULL;
-}
-
-#endif /* HAVE_STRCASESTR */
-
 struct tej_error_mgr 
 {
 	struct jpeg_error_mgr jpeg;
@@ -132,289 +107,6 @@ static void tracker_extract_jpeg_error_exit (j_common_ptr cinfo)
     longjmp(h->setjmp_buffer, 1);
 }
 
-#ifdef HAVE_LIBEXIF
-
-typedef gchar * (*PostProcessor) (const gchar*, gboolean *free_it);
-
-typedef struct {
-	ExifTag       tag;
-	const gchar  *name;
-	PostProcessor post;
-	const gchar  *rdf_class;
-	const gchar  *rdf_property;
-	const gchar  *urn_prefix;
-} TagType;
-
-static gchar *date_to_iso8601	(const gchar *exif_date, gboolean *free_it);
-static gchar *fix_focal_length	(const gchar *fl, gboolean *free_it);
-static gchar *fix_flash		(const gchar *flash, gboolean *free_it);
-static gchar *fix_fnumber	(const gchar *fn, gboolean *free_it);
-static gchar *fix_exposure_time (const gchar *et, gboolean *free_it);
-static gchar *fix_orientation   (const gchar *orientation, gboolean *free_it);
-static gchar *fix_metering_mode (const gchar *metering_mode, gboolean *free_it);
-static gchar *fix_white_balance (const gchar *white_balance, gboolean *free_it);
-
-static TagType tags[] = {
-	{ EXIF_TAG_PIXEL_Y_DIMENSION, NFO_PREFIX "height", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_PIXEL_X_DIMENSION, NFO_PREFIX "width", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_RELATED_IMAGE_WIDTH, NFO_PREFIX "width", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_DOCUMENT_NAME, NIE_PREFIX "title", NULL, NULL, NULL, NULL },
-	/* { -1, "Image:Album", NULL }, */
-	{ EXIF_TAG_DATE_TIME, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-	{ EXIF_TAG_DATE_TIME_ORIGINAL, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-	/* { -1, "Image:Keywords", NULL }, */
-	{ EXIF_TAG_ARTIST, NCO_PREFIX "creator", NULL, NCO_PREFIX "Contact", NCO_PREFIX "fullname", "urn:artist:%s"},
-	{ EXIF_TAG_USER_COMMENT, NIE_PREFIX "comment", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_IMAGE_DESCRIPTION, NIE_PREFIX "description", NULL, NULL, NULL, NULL },
-	/* { EXIF_TAG_SOFTWARE, "Image:Software", NULL }, */
-	{ EXIF_TAG_MAKE, NMM_PREFIX "camera", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_MODEL, NMM_PREFIX "camera", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_ORIENTATION, NFO_PREFIX "orientation", fix_orientation, NULL, NULL, NULL },
-	/* { EXIF_TAG_EXPOSURE_PROGRAM, "Image:ExposureProgram", NULL }, */
-	{ EXIF_TAG_EXPOSURE_TIME, NMM_PREFIX "exposureTime", fix_exposure_time, NULL, NULL, NULL },
-	{ EXIF_TAG_FNUMBER, NMM_PREFIX "fnumber", fix_fnumber, NULL, NULL, NULL },
-	{ EXIF_TAG_FLASH, NMM_PREFIX "flash", fix_flash, NULL, NULL, NULL },
-	{ EXIF_TAG_FOCAL_LENGTH, NMM_PREFIX "focalLength", fix_focal_length, NULL, NULL, NULL },
-	{ EXIF_TAG_ISO_SPEED_RATINGS, NMM_PREFIX "isoSpeed", NULL, NULL, NULL, NULL },
-	{ EXIF_TAG_METERING_MODE, NMM_PREFIX "meteringMode", fix_metering_mode, NULL, NULL, NULL },
-	{ EXIF_TAG_WHITE_BALANCE, NMM_PREFIX "whiteBalance", fix_white_balance, NULL, NULL, NULL },
-	{ EXIF_TAG_COPYRIGHT, NIE_PREFIX "copyright", NULL, NULL, NULL, NULL },
-	{ -1, NULL, NULL }
-};
-
-#endif /* HAVE_EXIF */
-
-#ifdef HAVE_LIBEXIF
-
-static gchar *
-date_to_iso8601 (const gchar *date, gboolean *free_it)
-{
-	/* From: ex; date "2007:04:15 15:35:58"
-	 * To  : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime */
-	*free_it = TRUE;
-	return tracker_date_format_to_iso8601 (date, EXIF_DATE_FORMAT);
-}
-
-static gchar *
-fix_focal_length (const gchar *fl, gboolean *free_it)
-{
-	*free_it = TRUE;
-	return g_strndup (fl, strstr (fl, " mm") - fl);
-}
-
-static gchar *
-fix_flash (const gchar *flash, gboolean *free_it)
-{
-	*free_it = FALSE;
-	
-	if (strcasestr (flash, "flash fired")) {
-		return (gchar *) "nmm:flash-on";
-	} else {
-		return (gchar *) "nmm:flash-off";
-	}
-}
-
-static gchar *
-fix_fnumber (const gchar *fn, gboolean *free_it)
-{
-	gchar *new_fn;
-
-	if (!fn) {
-		*free_it = FALSE;
-		return NULL;
-	}
-
-	new_fn = g_strdup (fn);
-
-	if (new_fn[0] == 'F') {
-		new_fn[0] = ' ';
-	} else if (fn[0] == 'f' && new_fn[1] == '/') {
-		new_fn[0] = new_fn[1] = ' ';
-	}
-
-	*free_it = TRUE;
-	return g_strstrip (new_fn);
-}
-
-static gchar *
-fix_exposure_time (const gchar *et, gboolean *free_it)
-{
-	gchar *sep;
-
-	sep = strchr (et, '/');
-
-	*free_it = TRUE;
-	
-	if (sep) {
-		gdouble fraction;
-
-		fraction = g_ascii_strtod (sep + 1, NULL);
-
-		if (fraction > 0.0) {
-			gdouble val;
-			gchar	buf[G_ASCII_DTOSTR_BUF_SIZE];
-
-			val = 1.0f / fraction;
-			g_ascii_dtostr (buf, sizeof(buf), val);
-
-			return g_strdup (buf);
-		}
-	}
-
-	return g_strdup (et);
-}
-
-static gchar *
-fix_orientation (const gchar *orientation, gboolean *free_it)
-{
-	guint i;
-	static const gchar *ostr[8] = {
-		/* 0 */ "top - left",
-		/* 1 */ "top - right",
-		/* 2 */ "bottom - right",
-		/* 3 */ "bottom - left",
-		/* 4 */ "left - top",
-		/* 5 */ "right - top",
-		/* 6 */ "right - bottom",
-		/* 7 */ "left - bottom"
-	};
-
-	*free_it = FALSE;
-	
-	for (i=0; i < 8; i++) {
-		if (g_strcmp0 (orientation,ostr[i]) == 0) {
-			switch (i) {
-				case 0:
-				return (gchar *) "nfo:orientation-top";
-				case 1:
-				return (gchar *) "nfo:orientation-top-mirror";
-				case 2:
-				return (gchar *) "nfo:orientation-bottom";
-				case 3:
-				return (gchar *) "nfo:orientation-bottom-mirror";
-				case 4:
-				return (gchar *) "nfo:orientation-left-mirror";
-				case 5:
-				return (gchar *) "nfo:orientation-right";
-				case 6:
-				return (gchar *) "nfo:orientation-right-mirror";
-				case 7:
-				return (gchar *) "nfo:orientation-left";
-				default:
-				break;
-			}
-		}
-	}
-
-	return (gchar *) "nfo:orientation-top";
-}
-
-
-static gchar *
-fix_metering_mode (const gchar *metering_mode, gboolean *free_it)
-{
-	*free_it = FALSE;
-	
-	if (strcasestr (metering_mode, "center")) {
-		return (gchar *) "nmm:meteringMode-center-weighted-average";
-	}
-
-	if (strcasestr (metering_mode, "average")) {
-		return (gchar *) "nmm:meteringMode-average";
-	}
-
-	if (strcasestr (metering_mode, "spot")) {
-		return (gchar *) "nmm:meteringMode-spot";
-	}
-
-	if (strcasestr (metering_mode, "multispot")) {
-		return (gchar *) "nmm:meteringMode-multispot";
-	}
-
-	if (strcasestr (metering_mode, "pattern")) {
-		return (gchar *) "nmm:meteringMode-pattern";
-	}
-
-	if (strcasestr (metering_mode, "partial")) {
-		return (gchar *) "nmm:meteringMode-partial";
-	}
-
-	return (gchar *) "nmm:meteringMode-other";
-}
-
-
-static gchar *
-fix_white_balance (const gchar *white_balance, gboolean *free_it)
-{
-	*free_it = FALSE;
-
-	if (strcasestr (white_balance, "auto")) {
-		return (gchar *) "nmm:whiteBalance-auto";
-	}
-
-	/* Found in the field: sunny, fluorescent, incandescent, cloudy. These
-	 * will this way also yield as manual. */
-
-	return (gchar *) "nmm:whiteBalance-manual";
-}
-
-static void
-read_exif (const unsigned char *buffer,
-	   size_t		len,
-	   const gchar         *uri,
-	   TrackerSparqlBuilder	       *metadata)
-{
-	ExifData *exif;
-	TagType  *p;
-
-	tracker_statement_list_insert (metadata, uri,
-	                               RDF_TYPE,
-	                               NMM_PREFIX "Photo");
-
-	exif = exif_data_new();
-	exif_data_set_option (exif, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
-	exif_data_unset_option (exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
-	exif_data_set_option (exif, EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE);
-
-	exif_data_load_data (exif, (unsigned char *) buffer, len);
-
-	for (p = tags; p->name; ++p) {
-		ExifEntry *entry = exif_data_get_entry (exif, p->tag);
-
-		if (entry) {
-			gchar buffer_[1024];
-			gchar *what_i_need;
-			gboolean free_it = FALSE;
-
-			exif_entry_get_value (entry, buffer_, 1024);
-
-			if (p->post) {
-				what_i_need = (*p->post) (buffer_, &free_it);
-			} else {
-				what_i_need = buffer_;
-			}
-
-			if (p->urn_prefix) {
-				gchar *canonical_uri = tracker_uri_printf_escaped (p->urn_prefix, what_i_need);
-				tracker_statement_list_insert (metadata, canonical_uri, RDF_TYPE, p->rdf_class);
-				tracker_statement_list_insert (metadata, canonical_uri, p->rdf_property, what_i_need);
-				tracker_statement_list_insert (metadata, uri, p->name, canonical_uri);
-				g_free (canonical_uri);
-			} else {
-				tracker_statement_list_insert (metadata, uri, p->name, what_i_need);
-			}
-
-			if (free_it)
-				g_free (what_i_need);
-		}
-	}
-	
-	exif_data_free (exif);
-}
-
-#endif /* HAVE_LIBEXIF */
-
-
 static void
 extract_jpeg (const gchar *uri,
 	      TrackerSparqlBuilder   *metadata)
@@ -437,6 +129,10 @@ extract_jpeg (const gchar *uri,
 	f = tracker_file_open (filename, "rb", FALSE);
 
 	if (f) {
+		TrackerXmpData xmp_data = { 0 };
+		TrackerExifData exif_data = { 0 };
+		TrackerIptcData iptc_data = { 0 };
+		JpegNeedsMergeData merge_data = { 0 };
 		gchar *str;
 		gsize  len;
 #ifdef HAVE_LIBIPTCDATA
@@ -445,8 +141,12 @@ extract_jpeg (const gchar *uri,
 #endif /* HAVE_LIBIPTCDATA */
 
 		tracker_statement_list_insert (metadata, uri, 
-		                          RDF_TYPE, 
-		                          NFO_PREFIX "Image");
+		                               RDF_PREFIX "type", 
+		                               NFO_PREFIX "Image");
+
+		tracker_statement_list_insert (metadata, uri,
+		                               RDF_PREFIX "type",
+		                               NMM_PREFIX "Photo");
 
 		cinfo.err = jpeg_std_error (&tejerr.jpeg);
 		tejerr.jpeg.error_exit = tracker_extract_jpeg_error_exit;
@@ -482,32 +182,39 @@ extract_jpeg (const gchar *uri,
 				str = g_strndup ((gchar*) marker->data, len);
 
 				tracker_statement_list_insert (metadata, uri,
-							  NIE_PREFIX "comment",
-							  str);
+				                               NIE_PREFIX "comment",
+				                               str);
+
 				g_free (str);
+
 				break;
-				
+
 			case JPEG_APP0+1:
 				str = (gchar*) marker->data;
 				len = marker->data_length;
 
 #ifdef HAVE_LIBEXIF
-				if (strncmp ("Exif", (gchar*) (marker->data), 5) == 0) {
-					read_exif ((unsigned char*) marker->data,
-						   marker->data_length, uri,
-						   metadata);
+				if (strncmp (EXIF_NAMESPACE, (gchar*) (marker->data), EXIF_NAMESPACE_LENGTH) == 0) {
+
+					tracker_read_exif ((unsigned char*) marker->data,
+					                   marker->data_length, 
+					                   uri, &exif_data);
 				}
 #endif /* HAVE_LIBEXIF */
 
 #ifdef HAVE_EXEMPI
-
 				if (strncmp (XMP_NAMESPACE, str, XMP_NAMESPACE_LENGTH) == 0) {
+					TrackerXmpData xmp_data = { 0 };
+
 					tracker_read_xmp (str + XMP_NAMESPACE_LENGTH,
 							  len - XMP_NAMESPACE_LENGTH,
-							  uri, metadata);
+							  uri, &xmp_data);
+
 				}
 #endif /* HAVE_EXEMPI */
+
 				break;
+
 			case JPEG_APP0+13:
 				str = (gchar*) marker->data;
 				len = marker->data_length;
@@ -516,12 +223,14 @@ extract_jpeg (const gchar *uri,
 					offset = iptc_jpeg_ps3_find_iptc (str, len, &sublen);
 					if (offset>0) {
 						tracker_read_iptc (str + offset,
-								   sublen,
-								   uri, metadata);
+						                   sublen,
+						                   uri, &iptc_data);
 					}
 				}
 #endif /* HAVE_LIBIPTCDATA */
+
 				break;
+
 			default:
 				marker = marker->next;
 				continue;
@@ -530,7 +239,63 @@ extract_jpeg (const gchar *uri,
 			marker = marker->next;
 		}
 
-		/* We want native size to have priority over EXIF, XMP etc */
+		merge_data.camera = tracker_coalesce (2, xmp_data.Model, 
+		                                      xmp_data.Make,
+		                                      exif_data.model,
+		                                      exif_data.make);
+
+		merge_data.title = tracker_coalesce (2, xmp_data.title,
+		                                     exif_data.document_name);
+
+		merge_data.orientation = tracker_coalesce (3, exif_data.orientation,
+		                                           xmp_data.Orientation,
+		                                           iptc_data.image_orientation);
+
+		merge_data.copyright = tracker_coalesce (3, exif_data.copyright,
+		                                         xmp_data.rights,
+		                                         iptc_data.copyright_notice);
+
+		merge_data.white_balance = tracker_coalesce (2, exif_data.white_balance,
+		                                             xmp_data.WhiteBalance);
+		                                             
+
+		merge_data.fnumber =  tracker_coalesce (2, exif_data.fnumber,
+		                                        xmp_data.FNumber);
+
+		merge_data.flash =  tracker_coalesce (2, exif_data.flash,
+		                                      xmp_data.Flash);
+
+		merge_data.focal_length =  tracker_coalesce (2, exif_data.focal_length,
+		                                             xmp_data.FocalLength);
+
+		merge_data.time_original =  tracker_coalesce (2, exif_data.time_original,
+		                                              xmp_data.DateTimeOriginal);
+
+		merge_data.artist =  tracker_coalesce (2, exif_data.artist,
+		                                       xmp_data.Artist,
+		                                       xmp_data.contributor);
+
+		merge_data.exposure_time =  tracker_coalesce (2, exif_data.exposure_time,
+		                                              xmp_data.ExposureTime);
+
+		merge_data.iso_speed_ratings =  tracker_coalesce (2, exif_data.iso_speed_ratings,
+		                                                  xmp_data.ISOSpeedRatings);
+
+		merge_data.date =  tracker_coalesce (3, exif_data.time, 
+		                                     xmp_data.date,
+		                                     iptc_data.date_created);
+
+		merge_data.description = tracker_coalesce (2, exif_data.description,
+		                                           xmp_data.description);
+
+		
+
+		merge_data.metering_mode =  tracker_coalesce (2, exif_data.metering_mode,
+		                                              xmp_data.MeteringMode);
+
+
+		g_free (exif_data.user_comment);
+
 		tracker_statement_list_insert_with_int (metadata, uri,
 						   NFO_PREFIX "width",
 						   cinfo.image_width);
@@ -538,6 +303,43 @@ extract_jpeg (const gchar *uri,
 						   NFO_PREFIX "height",
 						    cinfo.image_height);
 
+		g_free (exif_data.y_dimention);
+		g_free (exif_data.x_dimention);
+
+		g_free (xmp_data.creator);
+		g_free (xmp_data.keywords);
+		g_free (xmp_data.subject);
+		g_free (xmp_data.publisher);
+		g_free (xmp_data.type);
+		g_free (xmp_data.format);
+		g_free (xmp_data.identifier);
+		g_free (xmp_data.source);
+		g_free (xmp_data.language);
+		g_free (xmp_data.relation);
+		g_free (xmp_data.coverage);
+		g_free (xmp_data.license);
+
+		g_free (iptc_data.keywords);
+		g_free (iptc_data.byline);
+		g_free (iptc_data.credit);
+
+		g_free (merge_data.camera);
+		g_free (merge_data.title);
+		g_free (merge_data.orientation);
+		g_free (merge_data.copyright);
+		g_free (merge_data.white_balance);
+		g_free (merge_data.fnumber);
+		g_free (merge_data.flash);
+		g_free (merge_data.focal_length);
+		g_free (merge_data.time_original);
+		g_free (merge_data.artist);
+		g_free (merge_data.exposure_time);
+		g_free (merge_data.iso_speed_ratings);
+		g_free (merge_data.date);
+		g_free (merge_data.description);
+		g_free (merge_data.metering_mode);
+
+
 		jpeg_destroy_decompress (&cinfo);
 fail:
 		tracker_file_close (f, FALSE);
diff --git a/src/tracker-extract/tracker-iptc.c b/src/tracker-extract/tracker-iptc.c
index 575b9d2..00de234 100644
--- a/src/tracker-extract/tracker-iptc.c
+++ b/src/tracker-extract/tracker-iptc.c
@@ -20,23 +20,13 @@
 
 #include "config.h"
 
-#include <libtracker-common/tracker-ontology.h>
-#include <libtracker-common/tracker-statement-list.h>
-
 #include "tracker-iptc.h"
 #include "tracker-main.h"
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
-#define NIE_PREFIX TRACKER_NIE_PREFIX
-#define NCO_PREFIX TRACKER_NCO_PREFIX
-#define NFO_PREFIX TRACKER_NFO_PREFIX
-
 #include <glib.h>
 #include <string.h>
 
 #include <libtracker-common/tracker-type-utils.h>
-#include <libtracker-common/tracker-file-utils.h>
 
 #ifdef HAVE_LIBIPTCDATA
 
@@ -45,44 +35,6 @@
 
 #define IPTC_DATE_FORMAT "%Y %m %d"
 
-typedef const gchar * (*IptcPostProcessor) (const gchar*);
-
-typedef struct {
-	IptcRecord        record;
-	IptcTag           tag;
-	const gchar      *name;
-	IptcPostProcessor post;
-	const gchar      *urn;
-	const gchar      *rdf_type;
-	const gchar      *predicate;
-} IptcTagType;
-
-static const gchar *fix_iptc_orientation (const gchar *orientation);
-
-static gchar *
-date_to_iso8601 (const gchar *date)
-{
-	/* From: ex; date "2007:04:15 15:35:58"
-	* To : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime
-	*/
-	return tracker_date_format_to_iso8601 (date, IPTC_DATE_FORMAT);
-}
-
-static IptcTagType iptctags[] = {
-        { 2, IPTC_TAG_KEYWORDS, NIE_PREFIX "keyword", NULL, NULL, NULL, NULL }, /* We might have to strtok_r this one? */
-	/*	{ 2, IPTC_TAG_CONTENT_LOC_NAME, "Image:Location", NULL, NULL, NULL, NULL }, */
-	/*{ 2, IPTC_TAG_SUBLOCATION, "Image:Location", NULL, NULL, NULL, NULL },*/
-        { 2, IPTC_TAG_DATE_CREATED, NIE_PREFIX "contentCreated", date_to_iso8601, NULL, NULL, NULL },
-        /*{ 2, IPTC_TAG_ORIGINATING_PROGRAM, "Image:Software", NULL, NULL, NULL, NULL },*/
-        { 2, IPTC_TAG_BYLINE, NCO_PREFIX "creator", NULL, ":", NCO_PREFIX "Contact", NCO_PREFIX "fullname" },
-        /*{ 2, IPTC_TAG_CITY, "Image:City", NULL, NULL, NULL, NULL },*/
-        /*{ 2, IPTC_TAG_COUNTRY_NAME, "Image:Country", NULL, NULL, NULL, NULL },*/
-	{ 2, IPTC_TAG_CREDIT, NCO_PREFIX "creator", NULL, ":", NCO_PREFIX "Contact", NCO_PREFIX "fullname" },
-        { 2, IPTC_TAG_COPYRIGHT_NOTICE, NIE_PREFIX "copyright", NULL, NULL, NULL, NULL },
-        { 2, IPTC_TAG_IMAGE_ORIENTATION, NFO_PREFIX "orientation", fix_iptc_orientation, NULL, NULL, NULL },
-	{ -1, -1, NULL, NULL, NULL, NULL, NULL }
-};
-
 static const gchar *
 fix_iptc_orientation (const gchar *orientation)
 {
@@ -100,45 +52,73 @@ void
 tracker_read_iptc (const unsigned char *buffer,
 		   size_t		len,
 		   const gchar         *uri,
-		   TrackerSparqlBuilder   *metadata)
+		   TrackerIptcData     *data)
 {
 #ifdef HAVE_LIBIPTCDATA
-	IptcData     *iptc = NULL;
-	IptcTagType  *p = NULL;
+	guint i;
+	IptcData *iptc = NULL;
+	IptcTag   p[6] = { IPTC_TAG_KEYWORDS, 
+	         /* 01 */  IPTC_TAG_DATE_CREATED,
+	         /* 02 */  IPTC_TAG_BYLINE,
+	         /* 03 */  IPTC_TAG_CREDIT,
+	         /* 04 */  IPTC_TAG_COPYRIGHT_NOTICE,
+	         /* 05 */  IPTC_TAG_IMAGE_ORIENTATION};
+
+	/* FIXME According to valgrind this is leaking (together with the unref).
+	 * Problem in libiptc */
 
-	/* FIXME According to valgrind this is leaking (together with the unref). Problem in libiptc */
 	iptc = iptc_data_new ();
-       	if (!iptc)
+
+	if (!iptc)
 		return;
+
 	if (iptc_data_load (iptc, buffer, len) < 0) {
 		iptc_data_unref (iptc);
 		return;
 	}
 
-	for (p = iptctags; p->name; ++p) {
+	for (i = 0; i < 6; i++) {
 		IptcDataSet *dataset = NULL;
 
-		while ( (dataset = iptc_data_get_next_dataset (iptc, dataset, p->record, p->tag) ) ) {
+		while ((dataset = iptc_data_get_next_dataset (iptc, dataset, 2, p[i]))) {
 			gchar mbuffer[1024];
-			const gchar *what_i_need;
 
 			iptc_dataset_get_as_str (dataset, mbuffer, 1024);
-			
-			if (p->post) {
-				what_i_need = (*p->post) (mbuffer);
-			} else {
-				what_i_need = mbuffer;
-			}
 
-			if (p->urn) {
-				tracker_statement_list_insert (metadata, p->urn, RDF_TYPE, p->rdf_type);
-				tracker_statement_list_insert (metadata, p->urn, p->predicate, what_i_need);
-				tracker_statement_list_insert (metadata, uri, p->name, p->urn);
-			} else {
-				tracker_statement_list_insert (metadata, uri, p->name, what_i_need);
+			switch (p[i]) {
+				case IPTC_TAG_KEYWORDS:
+					if (!data->keywords)
+						data->keywords = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_DATE_CREATED:
+					if (!data->date_created) {
+						/* From: ex; date "2007:04:15 15:35:58"
+						* To : ex. "2007-04-15T17:35:58+0200 where +0200 is localtime */
+						data->date_created = tracker_date_format_to_iso8601 (mbuffer, IPTC_DATE_FORMAT);
+					}
+					break;
+				case IPTC_TAG_BYLINE:
+					if (!data->byline)
+						data->byline = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_CREDIT:
+					if (!data->credit)
+						data->credit = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_COPYRIGHT_NOTICE:
+					if (!data->copyright_notice)
+						data->copyright_notice = g_strdup (mbuffer);
+					break;
+				case IPTC_TAG_IMAGE_ORIENTATION:
+					if (!data->image_orientation)
+						data->image_orientation = g_strdup (fix_iptc_orientation (mbuffer));
+					break;
+				default:
+					break;
 			}
 		}
 	}
+
 	iptc_data_unref (iptc);
 
 #endif
diff --git a/src/tracker-extract/tracker-iptc.h b/src/tracker-extract/tracker-iptc.h
index c688844..ac6a817 100644
--- a/src/tracker-extract/tracker-iptc.h
+++ b/src/tracker-extract/tracker-iptc.h
@@ -1,12 +1,37 @@
+/* Tracker IPTC - Iptc helper functions
+ * Copyright (C) 2008, Nokia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Author: Philip Van Hoof <philip codeminded be>
+ */
 
 #ifndef _TRACKER_IPTC_H_
 #define _TRACKER_IPTC_H_
 
 #include <glib.h>
 
+typedef struct {
+	gchar *keywords, *date_created, *byline, *credit, *copyright_notice, 
+	      *image_orientation;
+} TrackerIptcData;
+
 void tracker_read_iptc (const unsigned char *buffer,
-			size_t		    len,
-			const gchar        *uri,
-			TrackerSparqlBuilder   *metadata);
+                        size_t               len,
+                        const gchar         *uri,
+                        TrackerIptcData     *data);
 
 #endif
diff --git a/src/tracker-extract/tracker-xmp.c b/src/tracker-extract/tracker-xmp.c
index 60c2cf6..ebfaa28 100644
--- a/src/tracker-extract/tracker-xmp.c
+++ b/src/tracker-extract/tracker-xmp.c
@@ -25,20 +25,10 @@
 
 #include <glib.h>
 
-#include <libtracker-common/tracker-ontology.h>
-#include <libtracker-common/tracker-statement-list.h>
-
 #include "tracker-main.h"
 #include "tracker-xmp.h"
 
-#define RDF_PREFIX TRACKER_RDF_PREFIX
-#define RDF_TYPE RDF_PREFIX "type"
-#define NIE_PREFIX TRACKER_NIE_PREFIX
-#define NFO_PREFIX TRACKER_NFO_PREFIX
-#define NCO_PREFIX TRACKER_NCO_PREFIX
-#define NMM_PREFIX TRACKER_NMM_PREFIX
-#define DC_PREFIX TRACKER_DC_PREFIX
-
+#include <libtracker-common/tracker-type-utils.h>
 #include <libtracker-common/tracker-utils.h>
 
 #ifdef HAVE_EXEMPI
@@ -49,10 +39,10 @@
 static void tracker_xmp_iter        (XmpPtr                xmp,
 				     XmpIteratorPtr        iter,
 				     const gchar          *uri,
-				     TrackerSparqlBuilder *metadata,
+				     TrackerXmpData       *data,
 				     gboolean              append);
 static void tracker_xmp_iter_simple (const gchar          *uri,
-				     TrackerSparqlBuilder *metadata,
+				     TrackerXmpData       *data,
 				     const gchar          *schema,
 				     const gchar          *path,
 				     const gchar          *value,
@@ -117,14 +107,14 @@ fix_white_balance (const gchar *wb)
 static void 
 tracker_xmp_iter_array (XmpPtr                xmp,
 			const gchar          *uri,
-			TrackerSparqlBuilder *metadata, 
+			TrackerXmpData       *data, 
 			const gchar          *schema, 
 			const gchar          *path)
 {
 	XmpIteratorPtr iter;
 
 	iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
-	tracker_xmp_iter (xmp, iter, uri, metadata, TRUE);
+	tracker_xmp_iter (xmp, iter, uri, data, TRUE);
 	xmp_iterator_free (iter);
 }
 
@@ -133,14 +123,14 @@ tracker_xmp_iter_array (XmpPtr                xmp,
 static void
 tracker_xmp_iter_alt_text (XmpPtr                xmp, 
 			   const gchar          *uri,
-			   TrackerSparqlBuilder *metadata, 
+			   TrackerXmpData       *data, 
 			   const gchar          *schema, 
 			   const gchar          *path)
 {
 	XmpIteratorPtr iter;
 
 	iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
-	tracker_xmp_iter (xmp, iter, uri, metadata, FALSE);
+	tracker_xmp_iter (xmp, iter, uri, data, FALSE);
 	xmp_iterator_free (iter);
 }
 
@@ -148,7 +138,7 @@ tracker_xmp_iter_alt_text (XmpPtr                xmp,
 static void
 tracker_xmp_iter_simple_qual (XmpPtr                xmp, 
 			      const gchar          *uri,
-			      TrackerSparqlBuilder *metadata,
+			      TrackerXmpData       *data,
 			      const gchar          *schema, 
 			      const gchar          *path, 
 			      const gchar          *value, 
@@ -194,7 +184,7 @@ tracker_xmp_iter_simple_qual (XmpPtr                xmp,
 	}
 
 	if (!ignore_element) {
-		tracker_xmp_iter_simple (uri, metadata, schema, path, value, append);
+		tracker_xmp_iter_simple (uri, data, schema, path, value, append);
 	}
 
 	xmp_string_free (the_prop);
@@ -247,12 +237,12 @@ fix_orientation (const gchar *orientation)
 }
 
 
-/* We have a simple element. Add any metadata we know about to the
+/* We have a simple element. Add any data we know about to the
  * hash table.
  */
 static void
 tracker_xmp_iter_simple (const gchar          *uri,
-			 TrackerSparqlBuilder *metadata,
+			 TrackerXmpData       *data,
 			 const gchar          *schema, 
 			 const gchar          *path, 
 			 const gchar          *value, 
@@ -270,203 +260,113 @@ tracker_xmp_iter_simple (const gchar          *uri,
 
 	/* Dublin Core */
 	if (strcmp (schema, NS_DC) == 0) {
-		if (strcmp (name, "title") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NIE_PREFIX "title", value);
+		if (strcmp (name, "title") == 0 && !data->title) {
+			data->title = g_strdup (value);
 		}
-		else if (strcmp (name, "rights") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "copyright", value);
+		else if (strcmp (name, "rights") == 0 && !data->rights) {
+			data->rights = g_strdup (value);
 		}
-		else if (strcmp (name, "creator") == 0) {
-
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "creator", ":");
-
+		else if (strcmp (name, "creator") == 0 && !data->creator) {
+			data->creator = g_strdup (value);
 		}
-		else if (strcmp (name, "description") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "description", value);
+		else if (strcmp (name, "description") == 0 && !data->description) {
+			data->description = g_strdup (value);
 		}
-		else if (strcmp (name, "date") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "contentCreated", value);
-		}
-		else if (strcmp (name, "keywords") == 0) {
-			gchar *keywords = g_strdup (value);
-			char *lasts, *keyw;
-			size_t len;
-
-			keyw = keywords;
-			keywords = strchr (keywords, '"');
-			if (keywords)
-				keywords++;
-			else 
-				keywords = keyw;
-
-			len = strlen (keywords);
-			if (keywords[len - 1] == '"')
-				keywords[len - 1] = '\0';
-
-			for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
-			     keyw = strtok_r (NULL, ",; ", &lasts)) {
-				tracker_statement_list_insert (metadata,
-						  uri, NIE_PREFIX "keyword",
-						  (const gchar*) keyw);
-			}
-
-			g_free (keyw);
+		else if (strcmp (name, "date") == 0 && !data->date) {
+			data->date = g_strdup (value);
 		}
-		else if (strcmp (name, "subject") == 0) {
-			gchar *keywords = g_strdup (value);
-			char *lasts, *keyw;
-			size_t len;
-
-			tracker_statement_list_insert (metadata, uri, 
-						  NIE_PREFIX "subject", value);
-
-			/* The subject field may contain keywords as well */
-
-			keyw = keywords;
-			keywords = strchr (keywords, '"');
-			if (keywords)
-				keywords++;
-			else 
-				keywords = keyw;
-
-			len = strlen (keywords);
-			if (keywords[len - 1] == '"')
-				keywords[len - 1] = '\0';
-
-			for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; 
-			     keyw = strtok_r (NULL, ",; ", &lasts)) {
-				tracker_statement_list_insert (metadata,
-						  uri, NIE_PREFIX "keyword",
-						  (const gchar*) keyw);
-			}
-
-			g_free (keyw);
-
+		else if (strcmp (name, "keywords") == 0 && !data->keywords) {
+			 data->keywords = g_strdup (value);
 		}
-		else if (strcmp (name, "publisher") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "publisher", ":");
+		else if (strcmp (name, "subject") == 0 && !data->subject) {
+			data->subject = g_strdup (value);
 		}
-		else if (strcmp (name, "contributor") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+		else if (strcmp (name, "publisher") == 0 && !data->publisher) {
+			data->publisher = g_strdup (value);
 		}
-		else if (strcmp (name, "type") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "type", value);
+		else if (strcmp (name, "contributor") == 0 && !data->contributor) {
+			data->contributor = g_strdup (value);
 		}
-		else if (strcmp (name, "format") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "format", value);
+		else if (strcmp (name, "type") == 0 && !data->type) {
+			data->type = g_strdup (value);
 		}
-		else if (strcmp (name, "identifier") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "identifier", value);
+		else if (strcmp (name, "format") == 0 && !data->format) {
+			data->format = g_strdup (value);
 		}
-		else if (strcmp (name, "source") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "source", value);
+		else if (strcmp (name, "identifier") == 0 && !data->identifier) {
+			data->identifier = g_strdup (value);
 		}
-		else if (strcmp (name, "language") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "language", value);
+		else if (strcmp (name, "source") == 0 && !data->source) {
+			data->source = g_strdup (value);
 		}
-		else if (strcmp (name, "relation") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  DC_PREFIX "relation", value);
+		else if (strcmp (name, "language") == 0 && !data->language) {
+			data->language = g_strdup (value);
 		}
-		else if (strcmp (name, "coverage") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  DC_PREFIX "coverage", value);
+		else if (strcmp (name, "relation") == 0 && !data->relation) {
+			data->relation = g_strdup (value);
+		}
+		else if (strcmp (name, "coverage") == 0 && !data->coverage) {
+			data->coverage = g_strdup (value);
 		}
 
 	}
 	/* Creative Commons */
 	else if (strcmp (schema, NS_CC) == 0) {
-		if (strcmp (name, "license") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "license", value);
+		if (strcmp (name, "license") == 0 && !data->license) {
+			data->license = g_strdup (value);
 		}
 	}
 	/* Exif basic scheme */
 	else if (strcmp (schema, NS_EXIF) == 0) {
-		if (strcmp (name, "Title") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NFO_PREFIX "title", value);
+		if (strcmp (name, "Title") == 0 && !data->Title) {
+			data->Title = g_strdup (value);
 		}
-		else if (strcmp (name, "DateTimeOriginal") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "contentCreated", value);
+		else if (strcmp (name, "DateTimeOriginal") == 0 && !data->DateTimeOriginal) {
+			data->DateTimeOriginal = g_strdup (value);
 		}
-		else if (strcmp (name, "Artist") == 0) {
-			tracker_statement_list_insert (metadata, ":", RDF_TYPE, NCO_PREFIX "Contact");
-			tracker_statement_list_insert (metadata, ":", NCO_PREFIX "fullname", value);
-			/* contributor is OK here? */
-			tracker_statement_list_insert (metadata, uri, NCO_PREFIX "contributor", ":");
+		else if (strcmp (name, "Artist") == 0 && !data->Artist) {
+			data->Artist = g_strdup (value);
 		}
 /*		else if (strcmp (name, "Software") == 0) {
 			tracker_statement_list_insert (metadata, uri,
 						  "Image:Software", value);
 		}*/
-		else if (strcmp (name, "Make") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "camera", value);
+		else if (strcmp (name, "Make") == 0 && !data->Make) {
+			data->Make = g_strdup (value);
 		}
-		else if (strcmp (name, "Model") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "camera", value);
+		else if (strcmp (name, "Model") == 0 && !data->Model) {
+			data->Model = g_strdup (value);
 		}
-		else if (strcmp (name, "Orientation") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NFO_PREFIX "orientation", 
-						  fix_orientation (value));
+		else if (strcmp (name, "Orientation") == 0 && !data->Orientation) {
+			data->Orientation = g_strdup (fix_orientation (value));
 		}
-		else if (strcmp (name, "Flash") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "flash", 
-						  fix_flash (value));
+		else if (strcmp (name, "Flash") == 0 && !data->Flash) {
+			data->Flash = g_strdup (fix_flash (value));
 		}
-		else if (strcmp (name, "MeteringMode") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "meteringMode", 
-						  fix_metering_mode (value));
+		else if (strcmp (name, "MeteringMode") == 0 && !data->MeteringMode) {
+			data->MeteringMode = g_strdup (fix_metering_mode (value));
 		}
 		/*else if (strcmp (name, "ExposureProgram") == 0) {
 			tracker_statement_list_insert (metadata, uri,
 						  "Image:ExposureProgram", value);
 		}*/
-		else if (strcmp (name, "ExposureTime") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "exposureTime", value);
+		else if (strcmp (name, "ExposureTime") == 0 && !data->ExposureTime) {
+			data->ExposureTime = g_strdup (value);
 		}
-		else if (strcmp (name, "FNumber") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NMM_PREFIX "fnumber", value);
+		else if (strcmp (name, "FNumber") == 0 && !data->FNumber) {
+			data->FNumber = g_strdup (value);
 		}
-		else if (strcmp (name, "FocalLength") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "focalLength", value);
+		else if (strcmp (name, "FocalLength") == 0 && !data->FocalLength) {
+			data->FocalLength = g_strdup (value);
 		}
-		else if (strcmp (name, "ISOSpeedRatings") == 0) {
-			tracker_statement_list_insert (metadata, uri, 
-						  NMM_PREFIX "isoSpeed", value);
+		else if (strcmp (name, "ISOSpeedRatings") == 0 && !data->ISOSpeedRatings) {
+			data->ISOSpeedRatings = g_strdup (value);
 		}
-		else if (strcmp (name, "WhiteBalance") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						   NMM_PREFIX "whiteBalance",
-						   fix_white_balance (value));
+		else if (strcmp (name, "WhiteBalance") == 0 && !data->WhiteBalance) {
+			data->WhiteBalance = g_strdup (fix_white_balance (value));
 		}
-		else if (strcmp (name, "Copyright") == 0) {
-			tracker_statement_list_insert (metadata, uri,
-						  NIE_PREFIX "copyright", value);
+		else if (strcmp (name, "Copyright") == 0 && !data->Copyright) {
+			data->Copyright = g_strdup (value);
 		}
 	}
 	/* XAP (XMP)scheme */
@@ -534,7 +434,7 @@ void
 tracker_xmp_iter (XmpPtr                xmp, 
 		  XmpIteratorPtr        iter, 
 		  const gchar          *uri,
-		  TrackerSparqlBuilder *metadata, 
+		  TrackerXmpData       *data, 
 		  gboolean              append)
 {
 	XmpStringPtr the_schema = xmp_string_new ();
@@ -550,18 +450,18 @@ tracker_xmp_iter (XmpPtr                xmp,
 		if (XMP_IS_PROP_SIMPLE (opt)) {
 			if (!tracker_is_empty_string (path)) {
 				if (XMP_HAS_PROP_QUALIFIERS (opt)) {
-					tracker_xmp_iter_simple_qual (xmp, uri, metadata, schema, path, value, append);
+					tracker_xmp_iter_simple_qual (xmp, uri, data, schema, path, value, append);
 				} else {
-					tracker_xmp_iter_simple (uri, metadata, schema, path, value, append);
+					tracker_xmp_iter_simple (uri, data, schema, path, value, append);
 				}
 			}
 		}
 		else if (XMP_IS_PROP_ARRAY (opt)) {
 			if (XMP_IS_ARRAY_ALTTEXT (opt)) {
-				tracker_xmp_iter_alt_text (xmp, uri, metadata, schema, path);
+				tracker_xmp_iter_alt_text (xmp, uri, data, schema, path);
 				xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
 			} else {
-				tracker_xmp_iter_array (xmp, uri, metadata, schema, path);
+				tracker_xmp_iter_array (xmp, uri, data, schema, path);
 				xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
 			}
 		}
@@ -578,7 +478,7 @@ void
 tracker_read_xmp (const gchar          *buffer, 
 		  size_t                len, 
 		  const gchar          *uri,
-		  TrackerSparqlBuilder *metadata)
+		  TrackerXmpData       *data)
 {
 #ifdef HAVE_EXEMPI
 	XmpPtr xmp;
@@ -592,7 +492,7 @@ tracker_read_xmp (const gchar          *buffer,
 		XmpIteratorPtr iter;
 
 		iter = xmp_iterator_new (xmp, NULL, NULL, XMP_ITER_PROPERTIES);
-		tracker_xmp_iter (xmp, iter, uri, metadata, FALSE);
+		tracker_xmp_iter (xmp, iter, uri, data, FALSE);
 		xmp_iterator_free (iter);
 		xmp_free (xmp);
 	}
diff --git a/src/tracker-extract/tracker-xmp.h b/src/tracker-extract/tracker-xmp.h
index fd4d7c6..f14b2c3 100644
--- a/src/tracker-extract/tracker-xmp.h
+++ b/src/tracker-extract/tracker-xmp.h
@@ -22,9 +22,30 @@
 
 #include <glib.h>
 
+typedef struct {
+	/* NS_DC */
+	gchar *title, *rights, *creator, *description, *date, *keywords, *subject,
+	      *publisher, *contributor, *type, *format, *identifier, *source,
+	      *language, *relation, *coverage;
+
+	/* NS_CC */
+	gchar *license;
+
+	/* NS_EXIF */
+	gchar *Title, *DateTimeOriginal, *Artist, *Make, *Model, *Orientation,
+	      *Flash, *MeteringMode, *ExposureTime, *FNumber, *FocalLength,
+	      *ISOSpeedRatings, *WhiteBalance, *Copyright;
+
+	/* TODO NS_XAP*/
+	/* TODO NS_IPTC4XMP */
+	/* TODO NS_PHOTOSHOP */
+
+} TrackerXmpData;
+
+
 void tracker_read_xmp (const gchar          *buffer, 
                        size_t                len, 
                        const gchar          *uri,
-                       TrackerSparqlBuilder *metadata);
+                       TrackerXmpData       *data);
 
 #endif /* _TRACKER_XMP_H_ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]