summaryrefslogtreecommitdiff
path: root/src/libtracker-extract/tracker-xmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtracker-extract/tracker-xmp.c')
-rw-r--r--src/libtracker-extract/tracker-xmp.c1165
1 files changed, 0 insertions, 1165 deletions
diff --git a/src/libtracker-extract/tracker-xmp.c b/src/libtracker-extract/tracker-xmp.c
deleted file mode 100644
index 911f3d7cf..000000000
--- a/src/libtracker-extract/tracker-xmp.c
+++ /dev/null
@@ -1,1165 +0,0 @@
-/*
- * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#include <locale.h>
-
-#include <libtracker-common/tracker-utils.h>
-
-#include "tracker-resource-helpers.h"
-#include "tracker-xmp.h"
-#include "tracker-utils.h"
-
-#ifdef HAVE_EXEMPI
-
-#define NS_XMP_REGIONS "http://www.metadataworkinggroup.com/schemas/regions/"
-#define NS_ST_DIM "http://ns.adobe.com/xap/1.0/sType/Dimensions#"
-#define NS_ST_AREA "http://ns.adobe.com/xmp/sType/Area#"
-
-#define REGION_LIST_REGEX "^mwg-rs:Regions/mwg-rs:RegionList\\[(\\d+)\\]"
-
-#include <exempi/xmp.h>
-#include <exempi/xmpconsts.h>
-
-/**
- * SECTION:tracker-xmp
- * @title: XMP
- * @short_description: Extensible Metadata Platform (XMP)
- * @stability: Stable
- * @include: libtracker-extract/tracker-extract.h
- *
- * The Adobe Extensible Metadata Platform (XMP) is a standard, created
- * by Adobe Systems Inc., for processing and storing standardized and
- * proprietary information relating to the contents of a file.
- *
- * XMP standardizes the definition, creation, and processing of
- * extensible metadata. Serialized XMP can be embedded into a
- * significant number of popular file formats, without breaking their
- * readability by non-XMP-aware applications. Embedding metadata ("the
- * truth is in the file") avoids many problems that occur when
- * metadata is stored separately. XMP is used in PDF, photography and
- * photo editing applications.
- *
- * This API is provided to remove code duplication between extractors
- * using these standards.
- **/
-
-static void iterate (XmpPtr xmp,
- XmpIteratorPtr iter,
- const gchar *uri,
- TrackerXmpData *data,
- gboolean append);
-static void iterate_simple (const gchar *uri,
- TrackerXmpData *data,
- const gchar *schema,
- const gchar *path,
- const gchar *value,
- gboolean append);
-
-static const gchar *
-fix_metering_mode (const gchar *mode)
-{
- gint value;
- value = atoi(mode);
-
- switch (value) {
- case 0:
- return "nmm:metering-mode-other";
- case 1:
- return "nmm:metering-mode-average";
- case 2:
- return "nmm:metering-mode-center-weighted-average";
- case 3:
- return "nmm:metering-mode-spot";
- case 4:
- return "nmm:metering-mode-multispot";
- case 5:
- return "nmm:metering-mode-pattern";
- case 6:
- return "nmm:metering-mode-partial";
- }
-
- return "nmm:metering-mode-other";
-}
-
-static const gchar *
-fix_flash (const gchar *flash)
-{
- static const gint fired_mask = 0x1;
- gint value;
-
- value = atoi (flash);
-
- if (value & fired_mask) {
- return "nmm:flash-on";
- } else {
- return "nmm:flash-off";
- }
-}
-
-static const gchar *
-fix_white_balance (const gchar *wb)
-{
- if (g_strcmp0 (wb, "1") == 0) {
- return "nmm:white-balance-manual";
- } else {
- return "nmm:white-balance-auto";
- }
-}
-
-static gchar *
-gps_coordinate_dup (const gchar *coordinates)
-{
- static GRegex *reg = NULL;
- GMatchInfo *info = NULL;
-
- if (!reg) {
- reg = g_regex_new ("([0-9]+),([0-9]+.[0-9]+)([A-Z])", 0, 0, NULL);
- }
-
- if (g_regex_match (reg, coordinates, 0, &info)) {
- gchar *deg,*min,*ref;
- gdouble r,d,m;
-
- deg = g_match_info_fetch (info, 1);
- min = g_match_info_fetch (info, 2);
- ref = g_match_info_fetch (info, 3);
-
- d = atof (deg);
- m = atof (min);
-
- r = d + m/60;
-
- if ( (ref[0] == 'S') || (ref[0] == 'W')) {
- r = r * -1;
- }
-
- g_free (deg);
- g_free (min);
- g_free (ref);
- g_match_info_free (info);
-
- return g_strdup_printf ("%f", r);
- } else {
- g_match_info_free (info);
- return NULL;
- }
-}
-
-/* We have an array, now recursively iterate over it's children. Set
- * 'append' to true so that all values of the array are added under
- * one entry.
- */
-static void
-iterate_array (XmpPtr xmp,
- const gchar *uri,
- TrackerXmpData *data,
- const gchar *schema,
- const gchar *path)
-{
- XmpIteratorPtr iter;
-
- iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
- iterate (xmp, iter, uri, data, TRUE);
- xmp_iterator_free (iter);
-}
-
-/* We have an array, now recursively iterate over it's children. Set
- * 'append' to false so that only one item is used.
- */
-static void
-iterate_alt_text (XmpPtr xmp,
- const gchar *uri,
- TrackerXmpData *data,
- const gchar *schema,
- const gchar *path)
-{
- XmpIteratorPtr iter;
-
- iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN);
- iterate (xmp, iter, uri, data, FALSE);
- xmp_iterator_free (iter);
-}
-
-static gchar *
-div_str_dup (const gchar *value)
-{
- gchar *ret;
- gchar *ptr = strchr (value, '/');
-
- if (ptr) {
- gchar *cpy = g_strdup (value);
- gint a, b;
-
- cpy [ptr - value] = '\0';
- a = atoi (cpy);
- b = atoi (cpy + (ptr - value) + 1);
-
- if (b != 0) {
- ret = g_strdup_printf ("%G", ((gdouble)((gdouble) a / (gdouble) b)));
- } else {
- ret = NULL;
- }
-
- g_free (cpy);
- } else {
- ret = g_strdup (value);
- }
-
- return ret;
-}
-
-/* We have a simple element, but need to iterate over the qualifiers */
-static void
-iterate_simple_qual (XmpPtr xmp,
- const gchar *uri,
- TrackerXmpData *data,
- const gchar *schema,
- const gchar *path,
- const gchar *value,
- gboolean append)
-{
- XmpIteratorPtr iter;
- XmpStringPtr the_path;
- XmpStringPtr the_prop;
- static gchar *locale = NULL;
- gboolean ignore_element = FALSE;
-
- iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN | XMP_ITER_JUSTLEAFNAME);
-
- the_path = xmp_string_new ();
- the_prop = xmp_string_new ();
-
- if (G_UNLIKELY (!locale)) {
- locale = g_strdup (setlocale (LC_ALL, NULL));
-
- if (!locale) {
- locale = g_strdup ("C");
- } else {
- gchar *sep;
-
- sep = strchr (locale, '.');
-
- if (sep) {
- locale[sep - locale] = '\0';
- }
-
- sep = strchr (locale, '_');
-
- if (sep) {
- locale[sep - locale] = '-';
- }
- }
- }
-
- while (xmp_iterator_next (iter, NULL, the_path, the_prop, NULL)) {
- const gchar *qual_path = xmp_string_cstr (the_path);
- const gchar *qual_value = xmp_string_cstr (the_prop);
-
- if (g_ascii_strcasecmp (qual_path, "xml:lang") == 0) {
- /* Is this a language we should ignore? */
- if (g_ascii_strcasecmp (qual_value, "x-default") != 0 &&
- g_ascii_strcasecmp (qual_value, "x-repair") != 0 &&
- g_ascii_strcasecmp (qual_value, locale) != 0) {
- ignore_element = TRUE;
- break;
- }
- }
- }
-
- if (!ignore_element) {
- iterate_simple (uri, data, schema, path, value, append);
- }
-
- xmp_string_free (the_prop);
- xmp_string_free (the_path);
-
- xmp_iterator_free (iter);
-}
-
-static const gchar *
-fix_orientation (const gchar *orientation)
-{
- if (orientation && g_ascii_strcasecmp (orientation, "1") == 0) {
- return "nfo:orientation-top";
- } else if (orientation && g_ascii_strcasecmp (orientation, "2") == 0) {
- return "nfo:orientation-top-mirror";
- } else if (orientation && g_ascii_strcasecmp (orientation, "3") == 0) {
- return "nfo:orientation-bottom";
- } else if (orientation && g_ascii_strcasecmp (orientation, "4") == 0) {
- return "nfo:orientation-bottom-mirror";
- } else if (orientation && g_ascii_strcasecmp (orientation, "5") == 0) {
- return "nfo:orientation-left-mirror";
- } else if (orientation && g_ascii_strcasecmp (orientation, "6") == 0) {
- return "nfo:orientation-right";
- } else if (orientation && g_ascii_strcasecmp (orientation, "7") == 0) {
- return "nfo:orientation-right-mirror";
- } else if (orientation && g_ascii_strcasecmp (orientation, "8") == 0) {
- return "nfo:orientation-left";
- }
-
- return "nfo:orientation-top";
-}
-
-/*
- * In a path like: mwg-rs:Regions/mwg-rs:RegionList[2]/mwg-rs:Area/stArea:x
- * this function returns the "2" from RegionsList[2]
- * Note: The first element from a list is 1
- */
-static gint
-get_region_counter (const gchar *path)
-{
- static GRegex *regex = NULL;
- GMatchInfo *match_info = NULL;
- gchar *match;
- gint result;
-
- if (!regex) {
- regex = g_regex_new (REGION_LIST_REGEX, 0, 0, NULL);
- }
-
- if (!g_regex_match (regex, path, 0, &match_info)) {
- g_match_info_free (match_info);
- return -1;
- }
-
- match = g_match_info_fetch (match_info, 1);
- result = g_strtod (match, NULL);
-
- g_free (match);
- g_match_info_free (match_info);
-
- return result;
-}
-
-
-
-/* We have a simple element. Add any data we know about to the
- * hash table.
- */
-static void
-iterate_simple (const gchar *uri,
- TrackerXmpData *data,
- const gchar *schema,
- const gchar *path,
- const gchar *value,
- gboolean append)
-{
- gchar *name;
- const gchar *p;
- gchar *propname;
-
- p = strchr (path, ':');
- if (!p) {
- return;
- }
-
- name = g_strdup (p + 1);
-
- /* For 'dc:subject[1]' the name will be 'subject'.
- * This rule doesn't work for RegionLists
- */
- p = strrchr (name, '[');
- if (p) {
- name[p - name] = '\0';
- }
-
- /* Exif basic scheme */
- if (g_ascii_strcasecmp (schema, NS_EXIF) == 0) {
- if (!data->title2 && g_ascii_strcasecmp (name, "Title") == 0) {
- data->title2 = g_strdup (value);
- } else if (g_ascii_strcasecmp (name, "DateTimeOriginal") == 0 && !data->time_original) {
- data->time_original = tracker_date_guess (value);
- } else if (!data->artist && g_ascii_strcasecmp (name, "Artist") == 0) {
- data->artist = g_strdup (value);
- /* } else if (g_ascii_strcasecmp (name, "Software") == 0) {
- tracker_statement_list_insert (metadata, uri,
- "Image:Software", value);*/
- } else if (!data->make && g_ascii_strcasecmp (name, "Make") == 0) {
- data->make = g_strdup (value);
- } else if (!data->model && g_ascii_strcasecmp (name, "Model") == 0) {
- data->model = g_strdup (value);
- } else if (!data->flash && g_ascii_strcasecmp (name, "Flash") == 0) {
- data->flash = g_strdup (fix_flash (value));
- } else if (!data->metering_mode && g_ascii_strcasecmp (name, "MeteringMode") == 0) {
- data->metering_mode = g_strdup (fix_metering_mode (value));
- /* } else if (g_ascii_strcasecmp (name, "ExposureProgram") == 0) {
- tracker_statement_list_insert (metadata, uri,
- "Image:ExposureProgram", value);*/
- } else if (!data->exposure_time && g_ascii_strcasecmp (name, "ExposureTime") == 0) {
- data->exposure_time = div_str_dup (value);
- } else if (!data->fnumber && g_ascii_strcasecmp (name, "FNumber") == 0) {
- data->fnumber = div_str_dup (value);
- } else if (!data->focal_length && g_ascii_strcasecmp (name, "FocalLength") == 0) {
- data->focal_length = div_str_dup (value);
- } else if (!data->iso_speed_ratings && g_ascii_strcasecmp (name, "ISOSpeedRatings") == 0) {
- data->iso_speed_ratings = div_str_dup (value);
- } else if (!data->white_balance && g_ascii_strcasecmp (name, "WhiteBalance") == 0) {
- data->white_balance = g_strdup (fix_white_balance (value));
- } else if (!data->copyright && g_ascii_strcasecmp (name, "Copyright") == 0) {
- data->copyright = g_strdup (value);
- } else if (!data->gps_altitude && g_ascii_strcasecmp (name, "GPSAltitude") == 0) {
- data->gps_altitude = div_str_dup (value);
- } else if (!data->gps_altitude_ref && g_ascii_strcasecmp (name, "GPSAltitudeRef") == 0) {
- data->gps_altitude_ref = g_strdup (value);
- } else if (!data->gps_latitude && g_ascii_strcasecmp (name, "GPSLatitude") == 0) {
- data->gps_latitude = gps_coordinate_dup (value);
- } else if (!data->gps_longitude && g_ascii_strcasecmp (name, "GPSLongitude") == 0) {
- data->gps_longitude = gps_coordinate_dup (value);
- } else if (!data->gps_direction && g_ascii_strcasecmp (name, "GPSImgDirection") == 0) {
- data->gps_direction = div_str_dup (value);
- }
- /* TIFF */
- } else if (g_ascii_strcasecmp (schema, NS_TIFF) == 0) {
- if (!data->orientation && g_ascii_strcasecmp (name, "Orientation") == 0) {
- data->orientation = g_strdup (fix_orientation (value));
- }
- /* PDF*/
- } else if (g_ascii_strcasecmp (schema, NS_PDF) == 0) {
- if (g_ascii_strcasecmp (name, "keywords") == 0) {
- if (data->pdf_keywords) {
- gchar *temp = g_strdup_printf ("%s, %s", value, data->pdf_keywords);
- g_free (data->pdf_keywords);
- data->pdf_keywords = temp;
- } else {
- data->pdf_keywords = g_strdup (value);
- }
- } else
- if (!data->pdf_title && g_ascii_strcasecmp (name, "title") == 0) {
- data->pdf_title = g_strdup (value);
- }
- /* Dublin Core */
- } else if (g_ascii_strcasecmp (schema, NS_DC) == 0) {
- if (!data->title && g_ascii_strcasecmp (name, "title") == 0) {
- data->title = g_strdup (value);
- } else if (!data->rights && g_ascii_strcasecmp (name, "rights") == 0) {
- data->rights = g_strdup (value);
- } else if (!data->creator && g_ascii_strcasecmp (name, "creator") == 0) {
- data->creator = g_strdup (value);
- } else if (!data->description && g_ascii_strcasecmp (name, "description") == 0) {
- data->description = g_strdup (value);
- } else if (!data->date && g_ascii_strcasecmp (name, "date") == 0) {
- data->date = tracker_date_guess (value);
- } else if (g_ascii_strcasecmp (name, "keywords") == 0) {
- if (data->keywords) {
- gchar *temp = g_strdup_printf ("%s, %s", value, data->keywords);
- g_free (data->keywords);
- data->keywords = temp;
- } else {
- data->keywords = g_strdup (value);
- }
- } else if (g_ascii_strcasecmp (name, "subject") == 0) {
- if (data->subject) {
- gchar *temp = g_strdup_printf ("%s, %s", value, data->subject);
- g_free (data->subject);
- data->subject = temp;
- } else {
- data->subject = g_strdup (value);
- }
- } else if (!data->publisher && g_ascii_strcasecmp (name, "publisher") == 0) {
- data->publisher = g_strdup (value);
- } else if (!data->contributor && g_ascii_strcasecmp (name, "contributor") == 0) {
- data->contributor = g_strdup (value);
- } else if (!data->type && g_ascii_strcasecmp (name, "type") == 0) {
- data->type = g_strdup (value);
- } else if (!data->format && g_ascii_strcasecmp (name, "format") == 0) {
- data->format = g_strdup (value);
- } else if (!data->identifier && g_ascii_strcasecmp (name, "identifier") == 0) {
- data->identifier = g_strdup (value);
- } else if (!data->source && g_ascii_strcasecmp (name, "source") == 0) {
- data->source = g_strdup (value);
- } else if (!data->language && g_ascii_strcasecmp (name, "language") == 0) {
- data->language = g_strdup (value);
- } else if (!data->relation && g_ascii_strcasecmp (name, "relation") == 0) {
- data->relation = g_strdup (value);
- } else if (!data->coverage && g_ascii_strcasecmp (name, "coverage") == 0) {
- data->coverage = g_strdup (value);
- }
- /* Creative Commons */
- } else if (g_ascii_strcasecmp (schema, NS_CC) == 0) {
- if (!data->license && g_ascii_strcasecmp (name, "license") == 0) {
- data->license = g_strdup (value);
- }
- /* TODO: A lot of these location fields are pretty vague and ambigious.
- * We should go through them one by one and ensure that all of them are
- * used sanely */
-
- /* Photoshop TODO: is this needed anyway? */
- } else if (g_ascii_strcasecmp (schema, NS_PHOTOSHOP) == 0) {
- if (!data->city && g_ascii_strcasecmp (name, "City") == 0) {
- data->city = g_strdup (value);
- } else if (!data->country && g_ascii_strcasecmp (name, "Country") == 0) {
- data->country = g_strdup (value);
- } else if (!data->state && g_ascii_strcasecmp (name, "State") == 0) {
- data->state = g_strdup (value);
- } else if (!data->address && g_ascii_strcasecmp (name, "Location") == 0) {
- data->address = g_strdup (value);
- }
- /* IPTC4XMP scheme - GeoClue / location stuff, TODO */
- } else if (g_ascii_strcasecmp (schema, NS_IPTC4XMP) == 0) {
- if (!data->city && g_ascii_strcasecmp (name, "City") == 0) {
- data->city = g_strdup (value);
- } else if (!data->country && g_ascii_strcasecmp (name, "Country") == 0) {
- data->country = g_strdup (value);
- } else if (!data->country && g_ascii_strcasecmp (name, "CountryName") == 0) {
- data->country = g_strdup (value);
- } else if (!data->country && g_ascii_strcasecmp (name, "PrimaryLocationName") == 0) {
- data->country = g_strdup (value);
- } else if (!data->state && g_ascii_strcasecmp (name, "State") == 0) {
- data->state = g_strdup (value);
- } else if (!data->state && g_ascii_strcasecmp (name, "Province") == 0) {
- data->state = g_strdup (value);
- } else if (!data->address && g_ascii_strcasecmp (name, "Sublocation") == 0) {
- data->address = g_strdup (value);
- }
- } else if (g_ascii_strcasecmp (schema, NS_XAP) == 0) {
- if (!data->rating && g_ascii_strcasecmp (name, "Rating") == 0) {
- data->rating = g_strdup (value);
- }
- } else if (g_ascii_strcasecmp (schema, NS_XMP_REGIONS) == 0) {
- if (g_str_has_prefix (path, "mwg-rs:Regions/mwg-rs:RegionList")) {
- TrackerXmpRegion *current_region;
- gint position = get_region_counter (path);
-
- if (position == -1) {
- g_free (name);
- return;
- }
-
- /* First time a property appear for a region, we create the region */
- current_region = g_slist_nth_data (data->regions, position-1);
- if (current_region == NULL) {
- current_region = g_slice_new0 (TrackerXmpRegion);
- data->regions = g_slist_append (data->regions, current_region);
- }
-
- propname = g_strdup (strrchr (path, '/') + 1);
-
- if (!current_region->title && g_ascii_strcasecmp (propname, "mwg-rs:Name") == 0) {
- current_region->title = g_strdup (value);
- } else if (!current_region->description && g_ascii_strcasecmp (propname, "mwg-rs:Description") == 0) {
- current_region->description = g_strdup (value);
- } else if (!current_region->x && g_ascii_strcasecmp (propname, "stArea:x") == 0) {
- current_region->x = g_strdup (value);
- } else if (!current_region->y && g_ascii_strcasecmp (propname, "stArea:y") == 0) {
- current_region->y = g_strdup (value);
- } else if (!current_region->width && g_ascii_strcasecmp (propname, "stArea:w") == 0) {
- current_region->width = g_strdup (value);
- } else if (!current_region->height && g_ascii_strcasecmp (propname, "stArea:h") == 0) {
- current_region->height = g_strdup (value);
-
- /* Spec not clear about units
- * } else if (!current_region->unit
- * && g_ascii_strcasecmp (propname, "stArea:unit") == 0) {
- * current_region->unit = g_strdup (value);
- *
- * we consider it always comes normalized
- */
- } else if (!current_region->type && g_ascii_strcasecmp (propname, "mwg-rs:Type") == 0) {
- current_region->type = g_strdup (value);
- } else if (!current_region->link_class && !current_region->link_uri &&
- g_str_has_prefix (strrchr (path, ']') + 2, "mwg-rs:Extensions")) {
- current_region->link_class = g_strdup (propname);
- current_region->link_uri = g_strdup (value);
- }
-
- g_free (propname);
- }
- }
-
- g_free (name);
-}
-
-
-/* Iterate over the XMP, dispatching to the appropriate element type
- * (simple, simple w/qualifiers, or an array) handler.
- */
-static void
-iterate (XmpPtr xmp,
- XmpIteratorPtr iter,
- const gchar *uri,
- TrackerXmpData *data,
- gboolean append)
-{
- XmpStringPtr the_schema = xmp_string_new ();
- XmpStringPtr the_path = xmp_string_new ();
- XmpStringPtr the_prop = xmp_string_new ();
-
- uint32_t opt;
-
- while (xmp_iterator_next (iter, the_schema, the_path, the_prop, &opt)) {
- const gchar *schema = xmp_string_cstr (the_schema);
- const gchar *path = xmp_string_cstr (the_path);
- const gchar *value = xmp_string_cstr (the_prop);
-
- if (XMP_IS_PROP_SIMPLE (opt)) {
- if (!tracker_is_empty_string (path)) {
- if (XMP_HAS_PROP_QUALIFIERS (opt)) {
- iterate_simple_qual (xmp, uri, data, schema, path, value, append);
- } else {
- iterate_simple (uri, data, schema, path, value, append);
- }
- }
- } else if (XMP_IS_PROP_ARRAY (opt)) {
- if (XMP_IS_ARRAY_ALTTEXT (opt)) {
- iterate_alt_text (xmp, uri, data, schema, path);
- xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
- } else {
- iterate_array (xmp, uri, data, schema, path);
-
- /* Some dc: elements are handled as arrays by exempi.
- * In those cases, to avoid duplicated values, is easier
- * to skip the subtree.
- */
- if (g_ascii_strcasecmp (schema, NS_DC) == 0) {
- xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE);
- }
- }
- }
- }
-
- xmp_string_free (the_prop);
- xmp_string_free (the_path);
- xmp_string_free (the_schema);
-}
-
-static void
-register_namespace (const gchar *ns_uri,
- const gchar *suggested_prefix)
-{
- if (!xmp_namespace_prefix (ns_uri, NULL)) {
- xmp_register_namespace (ns_uri, suggested_prefix, NULL);
- }
-}
-
-#endif /* HAVE_EXEMPI */
-
-static gboolean
-parse_xmp (const gchar *buffer,
- size_t len,
- const gchar *uri,
- TrackerXmpData *data)
-{
-#ifdef HAVE_EXEMPI
- XmpPtr xmp;
-#endif /* HAVE_EXEMPI */
-
- memset (data, 0, sizeof (TrackerXmpData));
-
-#ifdef HAVE_EXEMPI
-
- xmp_init ();
-
- register_namespace (NS_XMP_REGIONS, "mwg-rs");
- register_namespace (NS_ST_DIM, "stDim");
- register_namespace (NS_ST_AREA, "stArea");
-
- xmp = xmp_new_empty ();
- xmp_parse (xmp, buffer, len);
-
- if (xmp != NULL) {
- XmpIteratorPtr iter;
-
- iter = xmp_iterator_new (xmp, NULL, NULL, XMP_ITER_PROPERTIES);
- iterate (xmp, iter, uri, data, FALSE);
- xmp_iterator_free (iter);
- xmp_free (xmp);
- }
-
- xmp_terminate ();
-#endif /* HAVE_EXEMPI */
-
- return TRUE;
-}
-
-#ifndef TRACKER_DISABLE_DEPRECATED
-
-// LCOV_EXCL_START
-
-/**
- * tracker_xmp_read:
- * @buffer: a chunk of data with xmp data in it.
- * @len: the size of @buffer.
- * @uri: the URI this is related to.
- * @data: a pointer to a TrackerXmpData structure to populate.
- *
- * This function takes @len bytes of @buffer and runs it through the
- * XMP library. The result is that @data is populated with the XMP
- * data found in @uri.
- *
- * Returns: %TRUE if the @data was populated successfully, otherwise
- * %FALSE is returned.
- *
- * Since: 0.8
- *
- * Deprecated: 0.9. Use tracker_xmp_new() instead.
- **/
-gboolean
-tracker_xmp_read (const gchar *buffer,
- size_t len,
- const gchar *uri,
- TrackerXmpData *data)
-{
- g_return_val_if_fail (buffer != NULL, FALSE);
- g_return_val_if_fail (len > 0, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
-
- return parse_xmp (buffer, len, uri, data);
-}
-
-// LCOV_EXCL_STOP
-
-#endif /* TRACKER_DISABLE_DEPRECATED */
-
-static void
-xmp_region_free (gpointer data)
-{
- TrackerXmpRegion *region = (TrackerXmpRegion *) data;
-
- g_free (region->title);
- g_free (region->description);
- g_free (region->type);
- g_free (region->x);
- g_free (region->y);
- g_free (region->width);
- g_free (region->height);
- g_free (region->link_class);
- g_free (region->link_uri);
-
- g_slice_free (TrackerXmpRegion, region);
-}
-
-
-/**
- * tracker_xmp_new:
- * @buffer: a chunk of data with xmp data in it.
- * @len: the size of @buffer.
- * @uri: the URI this is related to.
- *
- * This function takes @len bytes of @buffer and runs it through the
- * XMP library.
- *
- * Returns: a newly allocated #TrackerXmpData struct if XMP data was
- * found, %NULL otherwise. Free the returned struct with tracker_xmp_free().
- *
- * Since: 0.10
- **/
-TrackerXmpData *
-tracker_xmp_new (const gchar *buffer,
- gsize len,
- const gchar *uri)
-{
- TrackerXmpData *data;
-
- g_return_val_if_fail (buffer != NULL, NULL);
- g_return_val_if_fail (len > 0, NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- data = g_new0 (TrackerXmpData, 1);
-
- if (!parse_xmp (buffer, len, uri, data)) {
- tracker_xmp_free (data);
- return NULL;
- }
-
- return data;
-}
-
-/**
- * tracker_xmp_free:
- * @data: a #TrackerXmpData struct
- *
- * Frees @data and all #TrackerXmpData members. %NULL will produce a
- * a warning.
- *
- * Since: 0.10
- **/
-void
-tracker_xmp_free (TrackerXmpData *data)
-{
- g_return_if_fail (data != NULL);
-
- g_free (data->title);
- g_free (data->rights);
- g_free (data->creator);
- g_free (data->description);
- g_free (data->date);
- g_free (data->keywords);
- g_free (data->subject);
- g_free (data->publisher);
- g_free (data->contributor);
- g_free (data->type);
- g_free (data->format);
- g_free (data->identifier);
- g_free (data->source);
- g_free (data->language);
- g_free (data->relation);
- g_free (data->coverage);
- g_free (data->license);
- g_free (data->pdf_title);
- g_free (data->pdf_keywords);
- g_free (data->title2);
- g_free (data->time_original);
- g_free (data->artist);
- g_free (data->make);
- g_free (data->model);
- g_free (data->orientation);
- g_free (data->flash);
- g_free (data->metering_mode);
- g_free (data->exposure_time);
- g_free (data->fnumber);
- g_free (data->focal_length);
- g_free (data->iso_speed_ratings);
- g_free (data->white_balance);
- g_free (data->copyright);
- g_free (data->rating);
- g_free (data->address);
- g_free (data->country);
- g_free (data->state);
- g_free (data->city);
- g_free (data->gps_altitude);
- g_free (data->gps_altitude_ref);
- g_free (data->gps_latitude);
- g_free (data->gps_longitude);
- g_free (data->gps_direction);
-
- g_slist_free_full (data->regions, xmp_region_free);
- g_free (data);
-}
-
-
-static const gchar *
-fix_region_type (const gchar *region_type)
-{
- if (region_type == NULL) {
- return "nfo:region-content-undefined";
- }
-
- if (g_ascii_strncasecmp (region_type, "Face", 4) == 0) {
- return "nfo:roi-content-face";
- } else if (g_ascii_strncasecmp (region_type, "Pet", 3) == 0) {
- return "nfo:roi-content-pet";
- } else if (g_ascii_strncasecmp (region_type, "Focus", 5) == 0) {
- return "nfo:roi-content-focus";
- } else if (g_ascii_strncasecmp (region_type, "BarCode", 7) == 0) {
- return "nfo:roi-content-barcode";
- }
-
- return "nfo:roi-content-undefined";
-}
-
-
-/**
- * tracker_xmp_apply_to_resource:
- * @resource: the #TrackerResource to apply XMP data to.
- * @data: the data to push into @resource.
- *
- * This function applies all data in @data to @resource.
- *
- * This function also calls tracker_xmp_apply_regions_to_resource(), so there
- * is no need to call both functions.
- *
- * Returns: %TRUE if the @data was applied to @resource successfully,
- * otherwise %FALSE is returned.
- *
- * Since: 1.10
- **/
-gboolean
-tracker_xmp_apply_to_resource (TrackerResource *resource,
- TrackerXmpData *data)
-{
- GPtrArray *keywords;
- guint i;
-
- g_return_val_if_fail (TRACKER_IS_RESOURCE (resource), FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
-
- keywords = g_ptr_array_new ();
-
- if (data->keywords) {
- tracker_keywords_parse (keywords, data->keywords);
- }
-
- if (data->subject) {
- tracker_keywords_parse (keywords, data->subject);
- }
-
- if (data->pdf_keywords) {
- tracker_keywords_parse (keywords, data->pdf_keywords);
- }
-
- for (i = 0; i < keywords->len; i++) {
- TrackerResource *label;
- gchar *p;
-
- p = g_ptr_array_index (keywords, i);
- label = tracker_extract_new_tag (p);
-
- tracker_resource_set_relation (resource, "nao:hasTag", label);
-
- g_free (p);
- g_object_unref (label);
- }
- g_ptr_array_free (keywords, TRUE);
-
- if (data->publisher) {
- TrackerResource *publisher;
-
- publisher = tracker_extract_new_contact (data->publisher);
- tracker_resource_set_relation (resource, "nco:publisher", publisher);
- g_object_unref (publisher);
- }
-
- if (data->type) {
- tracker_resource_set_string (resource, "dc:type", data->type);
- }
-
- if (data->format) {
- tracker_resource_set_string (resource, "dc:format", data->format);
- }
-
- if (data->identifier) {
- tracker_resource_set_string (resource, "dc:identifier", data->identifier);
- }
-
- if (data->source) {
- tracker_resource_set_string (resource, "dc:source", data->source);
- }
-
- if (data->language) {
- tracker_resource_set_string (resource, "dc:language", data->language);
- }
-
- if (data->relation) {
- tracker_resource_set_string (resource, "dc:relation", data->relation);
- }
-
- if (data->coverage) {
- tracker_resource_set_string (resource, "dc:coverage", data->coverage);
- }
-
- if (data->license) {
- tracker_resource_set_string (resource, "dc:license", data->license);
- }
-
- if (data->make || data->model) {
- TrackerResource *equipment;
-
- equipment = tracker_extract_new_equipment (data->make, data->model);
- tracker_resource_set_relation (resource, "nfo:equipment", equipment);
- g_object_unref (equipment);
- }
-
- if (data->title || data->title2 || data->pdf_title) {
- const gchar *final_title = tracker_coalesce_strip (3, data->title,
- data->title2,
- data->pdf_title);
-
- tracker_resource_set_string (resource, "nie:title", final_title);
- }
-
- if (data->orientation) {
- TrackerResource *orientation;
-
- orientation = tracker_resource_new (data->orientation);
- tracker_resource_set_relation (resource, "nfo:orientation", orientation);
- g_object_unref (orientation);
- }
-
- if (data->rights || data->copyright) {
- const gchar *final_rights = tracker_coalesce_strip (2, data->copyright, data->rights);
-
- tracker_resource_set_string (resource, "nie:copyright", final_rights);
- }
-
- if (data->white_balance) {
- TrackerResource *white_balance;
-
- white_balance = tracker_resource_new (data->white_balance);
- tracker_resource_set_relation (resource, "nmm:meteringMode", white_balance);
- g_object_unref (white_balance);
- }
-
- if (data->fnumber) {
- tracker_resource_set_string (resource, "nmm:fnumber", data->fnumber);
- }
-
- if (data->flash) {
- TrackerResource *flash;
-
- flash = tracker_resource_new (data->flash);
- tracker_resource_set_relation (resource, "nmm:flash", flash);
- g_object_unref (flash);
- }
-
- if (data->focal_length) {
- tracker_resource_set_string (resource, "nmm:focalLength", data->focal_length);
- }
-
- if (data->artist || data->contributor) {
- TrackerResource *contributor;
- const gchar *final_artist = tracker_coalesce_strip (2, data->artist, data->contributor);
-
- contributor = tracker_extract_new_contact (final_artist);
- tracker_resource_set_relation (resource, "nco:contributor", contributor);
- g_object_unref (contributor);
- }
-
- if (data->exposure_time) {
- tracker_resource_set_string (resource, "nmm:exposureTime", data->exposure_time);
- }
-
- if (data->iso_speed_ratings) {
- tracker_resource_set_string (resource, "nmm:isoSpeed", data->iso_speed_ratings);
- }
-
- if (data->date || data->time_original) {
- const gchar *final_date = tracker_coalesce_strip (2, data->date,
- data->time_original);
-
- tracker_resource_set_string (resource, "nie:contentCreated", final_date);
- }
-
- if (data->description) {
- tracker_resource_set_string (resource, "nie:description", data->description);
- }
-
- if (data->metering_mode) {
- TrackerResource *metering;
-
- metering = tracker_resource_new (data->metering_mode);
- tracker_resource_set_relation (resource, "nmm:meteringMode", metering);
- g_object_unref (metering);
- }
-
- if (data->creator) {
- TrackerResource *creator;
-
- creator = tracker_extract_new_contact (data->creator);
- tracker_resource_set_relation (resource, "nco:creator", creator);
- g_object_unref (creator);
- }
-
- if (data->address || data->state || data->country || data->city ||
- data->gps_altitude || data->gps_latitude || data->gps_longitude) {
- TrackerResource *geopoint;
-
- geopoint = tracker_extract_new_location (data->address, data->state, data->city,
- data->country, data->gps_altitude, data->gps_latitude, data->gps_longitude);
- tracker_resource_set_relation (resource, "slo:location", geopoint);
- g_object_unref (geopoint);
- }
-
- if (data->gps_direction) {
- tracker_resource_set_string (resource, "nfo:heading", data->gps_direction);
- }
-
- if (data->regions) {
- tracker_xmp_apply_regions_to_resource (resource, data);
- }
-
- return TRUE;
-}
-
-/**
- * tracker_xmp_apply_regions_to_resource:
- * @resource: the #TrackerResource object to apply XMP data to.
- * @data: the data to push into @resource
- *
- * This function applies all regional @data to @resource. Regional data exists
- * for image formats like JPEG, PNG, etc. where parts of the image refer to
- * areas of interest. This can be people's faces, places to focus, barcodes,
- * etc. The regional data describes the title, height, width, X, Y and can
- * occur multiple times in a given file.
- *
- * This data usually is standardized between image formats and that's
- * what makes this function different to tracker_xmp_apply_to_resource() which
- * is useful for XMP files only.
- *
- * Returns: %TRUE if the @data was applied to @resource successfully, otherwise
- * %FALSE is returned.
- *
- * Since: 1.10
- **/
-gboolean
-tracker_xmp_apply_regions_to_resource (TrackerResource *resource,
- TrackerXmpData *data)
-{
- GSList *iter;
-
- g_return_val_if_fail (TRACKER_IS_RESOURCE (resource), FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
-
- if (!data->regions) {
- return TRUE;
- }
-
- for (iter = data->regions; iter != NULL; iter = iter->next) {
- TrackerResource *region_resource;
- TrackerXmpRegion *region;
- gchar *uuid;
-
- region = (TrackerXmpRegion *) iter->data;
- uuid = tracker_sparql_get_uuid_urn ();
-
- region_resource = tracker_resource_new (uuid);
- tracker_resource_set_uri (region_resource, "rdf:type", "nfo:RegionOfInterest");
-
- g_free (uuid);
-
- if (region->title) {
- tracker_resource_set_string (region_resource, "nie:title", region->title);
- }
-
- if (region->description) {
- tracker_resource_set_string (region_resource, "nie:description", region->description);
- }
-
- if (region->type) {
- tracker_resource_set_string (region_resource, "nfo:regionOfInterestType", fix_region_type (region->type));
- }
-
- if (region->x) {
- tracker_resource_set_string (region_resource, "nfo:regionOfInterestX", region->x);
- }
-
- if (region->y) {
- tracker_resource_set_string (region_resource, "nfo:regionOfInterestY", region->y);
- }
-
- if (region->width) {
- tracker_resource_set_string (region_resource, "nfo:regionOfInterestWidth", region->width);
- }
-
- if (region->height) {
- tracker_resource_set_string (region_resource, "nfo:regionOfInterestHeight", region->height);
- }
-
- if (region->link_uri && region->link_class) {
- tracker_resource_set_string (region_resource, "nfo:roiRefersTo", region->link_uri);
- }
-
- tracker_resource_add_relation (resource, "nfo:hasRegionOfInterest", region_resource);
- g_object_unref (region_resource);
- }
-
- return TRUE;
-}