diff options
Diffstat (limited to 'src/libtracker-extract/tracker-xmp.c')
-rw-r--r-- | src/libtracker-extract/tracker-xmp.c | 1165 |
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; -} |