G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *preupdate, *metadata; goffset size; const gchar *graph; gchar *filename, *uri; GFile *file; preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); if (size < 14) { /* Smaller than BMP header, can't be a real BMP file */ g_free (filename); return FALSE; } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_object (metadata, "nmm:Photo"); /* TODO: Add actual metadata extraction for BMP files */ return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TotemPlParser *pl; TrackerSparqlBuilder *metadata; PlaylistMetadata data; GFile *file; gchar *uri; pl = totem_pl_parser_new (); file = tracker_extract_info_get_file (info); uri = g_file_get_uri (file); metadata = tracker_extract_info_get_metadata_builder (info); data.track_counter = PLAYLIST_DEFAULT_NO_TRACKS; data.total_time = PLAYLIST_DEFAULT_DURATION; data.title = NULL; data.metadata = metadata; g_object_set (pl, "recurse", FALSE, "disable-unsafe", TRUE, NULL); g_signal_connect (G_OBJECT (pl), "playlist-started", G_CALLBACK (playlist_started), &data); g_signal_connect (G_OBJECT (pl), "entry-parsed", G_CALLBACK (entry_parsed), &data); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:Playlist"); tracker_sparql_builder_object (metadata, "nfo:MediaList"); if (totem_pl_parser_parse (pl, uri, FALSE) == TOTEM_PL_PARSER_RESULT_SUCCESS) { if (data.title != NULL) { g_message ("Playlist title:'%s'", data.title); tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (metadata, data.title); g_free (data.title); } else { g_message ("Playlist has no title, attempting to get one from filename"); tracker_guarantee_title_from_file (metadata, "nie:title", NULL, uri, NULL); } if (data.total_time > 0) { tracker_sparql_builder_predicate (metadata, "nfo:listDuration"); tracker_sparql_builder_object_int64 (metadata, data.total_time); } if (data.track_counter > 0) { tracker_sparql_builder_predicate (metadata, "nfo:entryCounter"); tracker_sparql_builder_object_int64 (metadata, data.track_counter); } } else { g_warning ("Playlist could not be parsed, no error given"); } g_object_unref (pl); g_free (uri); return TRUE; }
static void write_pdf_data (PDFData data, TrackerSparqlBuilder *metadata, GPtrArray *keywords) { if (!tracker_is_empty_string (data.title)) { tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (metadata, data.title); } if (!tracker_is_empty_string (data.subject)) { tracker_sparql_builder_predicate (metadata, "nie:subject"); tracker_sparql_builder_object_unvalidated (metadata, data.subject); } if (!tracker_is_empty_string (data.author)) { tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, data.author); tracker_sparql_builder_object_blank_close (metadata); } if (!tracker_is_empty_string (data.date)) { tracker_sparql_builder_predicate (metadata, "nie:contentCreated"); tracker_sparql_builder_object_unvalidated (metadata, data.date); } if (!tracker_is_empty_string (data.keywords)) { tracker_keywords_parse (keywords, data.keywords); } }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *metadata; GFile *file; gchar *filename; DviContext *context; metadata = tracker_extract_info_get_metadata_builder (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); context = mdvi_init_context (filename); if (context == NULL) { g_warning ("Could not open dvi file '%s'\n", filename); g_free (filename); return FALSE; } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:PaginatedTextDocument"); tracker_sparql_builder_predicate (metadata, "nfo:pageCount"); tracker_sparql_builder_object_int64 (metadata, context->npages); if (context->fileid) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, context->fileid); } mdvi_destroy_context (context); return TRUE; }
static void process_directory (ProcessApplicationData *data, GFileInfo *file_info, GError **error) { TrackerSparqlBuilder *sparql; gchar *urn, *path, *uri; sparql = data->sparql; path = g_file_get_path (data->file); uri = g_file_get_uri (data->file); urn = tracker_sparql_escape_uri_printf ("urn:applications-dir:%s", path); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, urn); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); tracker_sparql_builder_object (sparql, "nie:DataObject"); tracker_sparql_builder_object (sparql, "nie:Folder"); tracker_sparql_builder_predicate (sparql, "tracker:available"); tracker_sparql_builder_object_boolean (sparql, TRUE); tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); tracker_sparql_builder_object_iri (sparql, urn); tracker_sparql_builder_predicate (sparql, "nie:url"); tracker_sparql_builder_object_string (sparql, uri); if (file_info) { guint64 time; time = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); tracker_sparql_builder_object_date (sparql, (time_t *) &time); } tracker_sparql_builder_insert_close (data->sparql); g_free (path); g_free (urn); g_free (uri); }
static gboolean extract_opf (const gchar *uri, const gchar *opf_path, TrackerExtractInfo *info) { GMarkupParseContext *context; OPFData *data = NULL; GError *error = NULL; gchar *dirname, *contents; GMarkupParser opf_parser = { opf_xml_start_element_handler, opf_xml_end_element_handler, opf_xml_text_handler, NULL, NULL }; g_debug ("Extracting OPF file contents from EPUB '%s'", uri); data = opf_data_new (info); tracker_sparql_builder_predicate (data->metadata, "a"); tracker_sparql_builder_object (data->metadata, "nfo:EBook"); /* Create parsing context */ context = g_markup_parse_context_new (&opf_parser, 0, data, NULL); /* Load the internal container file from the Zip archive, * and parse it to extract the .opf file to get metadata from */ tracker_gsf_parse_xml_in_zip (uri, opf_path, context, &error); g_markup_parse_context_free (context); if (error) { g_warning ("Could not get EPUB '%s' file: %s\n", opf_path, (error) ? error->message : "No error provided"); g_error_free (error); opf_data_free (data); return FALSE; } dirname = g_path_get_dirname (opf_path); contents = extract_opf_contents (uri, dirname, data->pages); g_free (dirname); if (contents && *contents) { tracker_sparql_builder_predicate (data->metadata, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (data->metadata, contents); } opf_data_free (data); g_free (contents); return TRUE; }
static void feed_removed (FeedSettings *setts, gchar *id, TrackerSparqlConnection *tracker_client) { TrackerSparqlBuilder *sparql; sparql = tracker_sparql_builder_new_update (); tracker_sparql_builder_delete_open (sparql, NULL); tracker_sparql_builder_subject_iri (sparql, id); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_delete_close (sparql); tracker_sparql_builder_where_open (sparql); tracker_sparql_builder_subject_iri (sparql, id); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_where_close (sparql); tracker_sparql_connection_update (tracker_client, tracker_sparql_builder_get_result (sparql), 0, NULL, NULL); g_object_unref (sparql); }
static void entry_parsed (TotemPlParser *parser, gchar *to_uri, GHashTable *to_metadata, gpointer user_data) { PlaylistMetadata *data; data = (PlaylistMetadata *) user_data; data->track_counter++; if (data->track_counter > 1000) { /* limit playlists to 1000 entries for query performance reasons */ g_message ("Playlist has > 1000 entries. Ignoring for performance reasons."); return; } if (data->track_counter == 1) { /* first track, predicate needed */ tracker_sparql_builder_predicate (data->metadata, "nfo:hasMediaFileListEntry"); } tracker_sparql_builder_object_blank_open (data->metadata); tracker_sparql_builder_predicate (data->metadata, "a"); tracker_sparql_builder_object (data->metadata, "nfo:MediaFileListEntry"); tracker_sparql_builder_predicate (data->metadata, "nfo:entryUrl"); tracker_sparql_builder_object_unvalidated (data->metadata, to_uri); tracker_sparql_builder_predicate (data->metadata, "nfo:listPosition"); tracker_sparql_builder_object_int64 (data->metadata, (gint64) data->track_counter); tracker_sparql_builder_object_blank_close (data->metadata); if (to_metadata) { gchar *duration; duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION); if (duration == NULL) { duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION_MS); } if (duration != NULL) { gint64 secs = totem_pl_parser_parse_duration (duration, FALSE); if (secs > 0) { data->total_time += secs; } } } }
static void open_insert (TrackerSparqlBuilder *preupdate, const char *graph, const gchar *iri, const gchar *type) { tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, iri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, type); }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *metadata; TrackerConfig *config; gchar *content; config = tracker_main_get_config (); metadata = tracker_extract_info_get_metadata_builder (info); content = get_file_content (tracker_extract_info_get_file (info), tracker_config_get_max_bytes (config)); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:PlainTextDocument"); if (content) { tracker_sparql_builder_predicate (metadata, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (metadata, content); g_free (content); } return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TIFF *image; TrackerXmpData *xd = NULL; TrackerIptcData *id = NULL; TrackerExifData *ed = NULL; MergeData md = { 0 }; TiffData td = { 0 }; gchar *filename, *uri; gchar *date; glong exif_offset; GPtrArray *keywords; guint i; GFile *file; TrackerSparqlBuilder *metadata, *preupdate; const gchar *graph, *urn; int fd; #ifdef HAVE_LIBIPTCDATA gchar *iptc_offset; guint32 iptc_size; #endif #ifdef HAVE_EXEMPI gchar *xmp_offset; guint32 size; #endif /* HAVE_EXEMPI */ file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); urn = tracker_extract_info_get_urn (info); fd = tracker_file_open_fd (filename); if (fd == -1) { g_warning ("Could not open tiff file '%s': %s\n", filename, g_strerror (errno)); g_free (filename); return FALSE; } if ((image = TIFFFdOpen (fd, filename, "r")) == NULL){ g_warning ("Could not open image:'%s'\n", filename); g_free (filename); close (fd); return FALSE; } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_object (metadata, "nmm:Photo"); uri = g_file_get_uri (file); #ifdef HAVE_LIBIPTCDATA if (TIFFGetField (image, TIFFTAG_RICHTIFFIPTC, &iptc_size, &iptc_offset)) { if (TIFFIsByteSwapped(image) != 0) { TIFFSwabArrayOfLong((uint32*) iptc_offset, (unsigned long) iptc_size); } id = tracker_iptc_new (iptc_offset, 4 * iptc_size, uri); } #endif /* HAVE_LIBIPTCDATA */ if (!id) { id = g_new0 (TrackerIptcData, 1); } /* FIXME There are problems between XMP data embedded with different tools due to bugs in the original spec (type) */ #ifdef HAVE_EXEMPI if (TIFFGetField (image, TIFFTAG_XMLPACKET, &size, &xmp_offset)) { xd = tracker_xmp_new (xmp_offset, size, uri); } #endif /* HAVE_EXEMPI */ if (!xd) { xd = g_new0 (TrackerXmpData, 1); } ed = g_new0 (TrackerExifData, 1); /* Get Tiff specifics */ td.width = tag_to_string (image, TIFFTAG_IMAGEWIDTH, TAG_TYPE_UINT32); td.length = tag_to_string (image, TIFFTAG_IMAGELENGTH, TAG_TYPE_UINT32); td.artist = tag_to_string (image, TIFFTAG_ARTIST, TAG_TYPE_STRING); td.copyright = tag_to_string (image, TIFFTAG_COPYRIGHT, TAG_TYPE_STRING); date = tag_to_string (image, TIFFTAG_DATETIME, TAG_TYPE_STRING); td.date = tracker_date_guess (date); g_free (date); td.title = tag_to_string (image, TIFFTAG_DOCUMENTNAME, TAG_TYPE_STRING); td.description = tag_to_string (image, TIFFTAG_IMAGEDESCRIPTION, TAG_TYPE_STRING); td.make = tag_to_string (image, TIFFTAG_MAKE, TAG_TYPE_STRING); td.model = tag_to_string (image, TIFFTAG_MODEL, TAG_TYPE_STRING); td.orientation = get_orientation (image); /* Get Exif specifics */ if (TIFFGetField (image, TIFFTAG_EXIFIFD, &exif_offset)) { if (TIFFReadEXIFDirectory (image, exif_offset)) { ed->exposure_time = tag_to_string (image, EXIFTAG_EXPOSURETIME, TAG_TYPE_DOUBLE); ed->fnumber = tag_to_string (image, EXIFTAG_FNUMBER, TAG_TYPE_DOUBLE); ed->iso_speed_ratings = tag_to_string (image, EXIFTAG_ISOSPEEDRATINGS, TAG_TYPE_C16_UINT16); date = tag_to_string (image, EXIFTAG_DATETIMEORIGINAL, TAG_TYPE_STRING); ed->time_original = tracker_date_guess (date); g_free (date); ed->metering_mode = get_metering_mode (image); ed->flash = get_flash (image); ed->focal_length = tag_to_string (image, EXIFTAG_DATETIMEORIGINAL, TAG_TYPE_DOUBLE); ed->white_balance = get_white_balance (image); /* ed->software = tag_to_string (image, EXIFTAG_SOFTWARE, TAG_TYPE_STRING); */ } } TIFFClose (image); g_free (filename); md.title = tracker_coalesce_strip (5, xd->title, xd->pdf_title, td.title, ed->document_name, xd->title2); md.orientation = tracker_coalesce_strip (4, xd->orientation, td.orientation, ed->orientation, id->image_orientation); md.copyright = tracker_coalesce_strip (4, xd->rights, td.copyright, ed->copyright, id->copyright_notice); md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); md.artist = tracker_coalesce_strip (4, xd->artist, td.artist, ed->artist, xd->contributor); md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); md.date = tracker_coalesce_strip (6, xd->date, xd->time_original, td.date, ed->time, id->date_created, ed->time_original); md.description = tracker_coalesce_strip (3, xd->description, td.description, ed->description); md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); md.city = tracker_coalesce_strip (2, xd->city, id->city); md.state = tracker_coalesce_strip (2, xd->state, id->state); md.address = tracker_coalesce_strip (2, xd->address, id->sublocation); md.country = tracker_coalesce_strip (2, xd->country, id->country_name); /* FIXME We are not handling the altitude ref here for xmp */ md.gps_altitude = tracker_coalesce_strip (2, xd->gps_altitude, ed->gps_altitude); md.gps_latitude = tracker_coalesce_strip (2, xd->gps_latitude, ed->gps_latitude); md.gps_longitude = tracker_coalesce_strip (2, xd->gps_longitude, ed->gps_longitude); md.gps_direction = tracker_coalesce_strip (2, xd->gps_direction, ed->gps_direction); md.creator = tracker_coalesce_strip (3, xd->creator, id->byline, id->credit); md.x_dimension = tracker_coalesce_strip (2, td.width, ed->x_dimension); md.y_dimension = tracker_coalesce_strip (2, td.length, ed->y_dimension); md.make = tracker_coalesce_strip (3, xd->make, td.make, ed->make); md.model = tracker_coalesce_strip (3, xd->model, td.model, ed->model); keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); if (ed->user_comment) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, ed->user_comment); } if (md.x_dimension) { tracker_sparql_builder_predicate (metadata, "nfo:width"); tracker_sparql_builder_object_unvalidated (metadata, md.x_dimension); } if (md.y_dimension) { tracker_sparql_builder_predicate (metadata, "nfo:height"); tracker_sparql_builder_object_unvalidated (metadata, md.y_dimension); } if (xd->keywords) { tracker_keywords_parse (keywords, xd->keywords); } if (xd->pdf_keywords) { tracker_keywords_parse (keywords, xd->pdf_keywords); } if (xd->subject) { tracker_keywords_parse (keywords, xd->subject); } if (xd->publisher) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->publisher); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, xd->publisher); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:publisher"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (xd->type) { tracker_sparql_builder_predicate (metadata, "dc:type"); tracker_sparql_builder_object_unvalidated (metadata, xd->type); } if (xd->format) { tracker_sparql_builder_predicate (metadata, "dc:format"); tracker_sparql_builder_object_unvalidated (metadata, xd->format); } if (xd->identifier) { tracker_sparql_builder_predicate (metadata, "dc:identifier"); tracker_sparql_builder_object_unvalidated (metadata, xd->identifier); } if (xd->source) { tracker_sparql_builder_predicate (metadata, "dc:source"); tracker_sparql_builder_object_unvalidated (metadata, xd->source); } if (xd->language) { tracker_sparql_builder_predicate (metadata, "dc:language"); tracker_sparql_builder_object_unvalidated (metadata, xd->language); } if (xd->relation) { tracker_sparql_builder_predicate (metadata, "dc:relation"); tracker_sparql_builder_object_unvalidated (metadata, xd->relation); } if (xd->coverage) { tracker_sparql_builder_predicate (metadata, "dc:coverage"); tracker_sparql_builder_object_unvalidated (metadata, xd->coverage); } if (xd->rating) { tracker_sparql_builder_predicate (metadata, "nao:numericRating"); tracker_sparql_builder_object_unvalidated (metadata, xd->rating); } if (xd->license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, xd->license); } if (xd->regions) { tracker_xmp_apply_regions (preupdate, metadata, graph, xd); } if (md.address || md.state || md.country || md.city || md.gps_altitude || md.gps_latitude || md.gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:location"); tracker_sparql_builder_object_blank_open (metadata); /* GeoPoint */ tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "slo:GeoLocation"); if (md.address || md.state || md.country || md.city) { gchar *addruri; addruri = tracker_sparql_get_uuid_urn (); tracker_sparql_builder_predicate (metadata, "slo:postalAddress"); tracker_sparql_builder_object_iri (metadata, addruri); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, addruri); g_free (addruri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:PostalAddress"); if (md.address) { tracker_sparql_builder_predicate (preupdate, "nco:streetAddress"); tracker_sparql_builder_object_unvalidated (preupdate, md.address); } if (md.state) { tracker_sparql_builder_predicate (preupdate, "nco:region"); tracker_sparql_builder_object_unvalidated (preupdate, md.state); } if (md.city) { tracker_sparql_builder_predicate (preupdate, "nco:locality"); tracker_sparql_builder_object_unvalidated (preupdate, md.city); } if (md.country) { tracker_sparql_builder_predicate (preupdate, "nco:country"); tracker_sparql_builder_object_unvalidated (preupdate, md.country); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (md.gps_altitude) { tracker_sparql_builder_predicate (metadata, "slo:altitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_altitude); } if (md.gps_latitude) { tracker_sparql_builder_predicate (metadata, "slo:latitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_latitude); } if (md.gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:longitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_longitude); } tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */ } if (md.gps_direction) { tracker_sparql_builder_predicate (metadata, "nfo:heading"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_direction); } if (id->contact) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", id->contact); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, id->contact); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:representative"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (id->keywords) { tracker_keywords_parse (keywords, id->keywords); } for (i = 0; i < keywords->len; i++) { gchar *escaped, *subject; const gchar *p; p = g_ptr_array_index (keywords, i); escaped = tracker_sparql_escape_string (p); subject = g_strdup_printf ("_:tag%d", i + 1); /* ensure tag with specified label exists */ tracker_sparql_builder_insert_open (preupdate, graph); tracker_sparql_builder_subject (preupdate, subject); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nao:Tag"); tracker_sparql_builder_predicate (preupdate, "nao:prefLabel"); tracker_sparql_builder_object_unvalidated (preupdate, escaped); tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_append (preupdate, "WHERE { FILTER (NOT EXISTS { " "?tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\" }) }\n"); /* associate file with tag */ tracker_sparql_builder_insert_open (preupdate, graph); tracker_sparql_builder_subject_iri (preupdate, urn); tracker_sparql_builder_predicate (preupdate, "nao:hasTag"); tracker_sparql_builder_object (preupdate, "?tag"); tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject (preupdate, "?tag"); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nao:Tag"); tracker_sparql_builder_predicate (preupdate, "nao:prefLabel"); tracker_sparql_builder_object_unvalidated (preupdate, escaped); tracker_sparql_builder_where_close (preupdate); g_free (subject); g_free (escaped); } g_ptr_array_free (keywords, TRUE); if (md.make || md.model) { gchar *equip_uri; equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", md.make ? md.make : "", md.model ? md.model : ""); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, equip_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nfo:Equipment"); if (md.make) { tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer"); tracker_sparql_builder_object_unvalidated (preupdate, md.make); } if (md.model) { tracker_sparql_builder_predicate (preupdate, "nfo:model"); tracker_sparql_builder_object_unvalidated (preupdate, md.model); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nfo:equipment"); tracker_sparql_builder_object_iri (metadata, equip_uri); g_free (equip_uri); } tracker_guarantee_title_from_file (metadata, "nie:title", md.title, uri, NULL); if (md.orientation) { tracker_sparql_builder_predicate (metadata, "nfo:orientation"); tracker_sparql_builder_object_unvalidated (metadata, md.orientation); } if (md.copyright) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, md.copyright); } if (md.white_balance) { tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance"); tracker_sparql_builder_object_unvalidated (metadata, md.white_balance); } if (md.fnumber) { tracker_sparql_builder_predicate (metadata, "nmm:fnumber"); tracker_sparql_builder_object_unvalidated (metadata, md.fnumber); } if (md.flash) { tracker_sparql_builder_predicate (metadata, "nmm:flash"); tracker_sparql_builder_object_unvalidated (metadata, md.flash); } if (md.focal_length) { tracker_sparql_builder_predicate (metadata, "nmm:focalLength"); tracker_sparql_builder_object_unvalidated (metadata, md.focal_length); } if (md.artist) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.artist); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.artist); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:contributor"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (md.exposure_time) { tracker_sparql_builder_predicate (metadata, "nmm:exposureTime"); tracker_sparql_builder_object_unvalidated (metadata, md.exposure_time); } if (md.iso_speed_ratings) { tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed"); tracker_sparql_builder_object_unvalidated (metadata, md.iso_speed_ratings); } tracker_guarantee_date_from_file_mtime (metadata, "nie:contentCreated", md.date, uri); if (md.description) { tracker_sparql_builder_predicate (metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (metadata, md.description); } if (md.metering_mode) { tracker_sparql_builder_predicate (metadata, "nmm:meteringMode"); tracker_sparql_builder_object_unvalidated (metadata, md.metering_mode); } if (md.creator) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); /* NOTE: We only have affiliation with * nco:PersonContact and we are using * nco:Contact here. */ /* if (id->byline_title) { */ /* tracker_sparql_builder_insert_open (preupdate, NULL); */ /* tracker_sparql_builder_subject (preupdate, "_:affiliation_by_line"); */ /* tracker_sparql_builder_predicate (preupdate, "a"); */ /* tracker_sparql_builder_object (preupdate, "nco:Affiliation"); */ /* tracker_sparql_builder_predicate (preupdate, "nco:title"); */ /* tracker_sparql_builder_object_unvalidated (preupdate, id->byline_title); */ /* tracker_sparql_builder_insert_close (preupdate); */ /* tracker_sparql_builder_predicate (metadata, "a"); */ /* tracker_sparql_builder_object (metadata, "nco:PersonContact"); */ /* tracker_sparql_builder_predicate (metadata, "nco:hasAffiliation"); */ /* tracker_sparql_builder_object (metadata, "_:affiliation_by_line"); */ /* } */ tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (ed->x_resolution) { gdouble value; value = ed->resolution_unit != 3 ? g_strtod (ed->x_resolution, NULL) : g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; tracker_sparql_builder_predicate (metadata, "nfo:horizontalResolution"); tracker_sparql_builder_object_double (metadata, value); } if (ed->y_resolution) { gdouble value; value = ed->resolution_unit != 3 ? g_strtod (ed->y_resolution, NULL) : g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; tracker_sparql_builder_predicate (metadata, "nfo:verticalResolution"); tracker_sparql_builder_object_double (metadata, value); } tiff_data_free (&td); tracker_exif_free (ed); tracker_xmp_free (xd); tracker_iptc_free (id); g_free (uri); close (fd); return TRUE; }
static void read_metadata (TrackerSparqlBuilder *preupdate, TrackerSparqlBuilder *metadata, GString *where, png_structp png_ptr, png_infop info_ptr, png_infop end_ptr, const gchar *uri, const gchar *graph) { MergeData md = { 0 }; PngData pd = { 0 }; TrackerExifData *ed = NULL; TrackerXmpData *xd = NULL; png_infop info_ptrs[2]; png_textp text_ptr; gint info_index; gint num_text; gint i; gint found; GPtrArray *keywords; info_ptrs[0] = info_ptr; info_ptrs[1] = end_ptr; for (info_index = 0; info_index < 2; info_index++) { if ((found = png_get_text (png_ptr, info_ptrs[info_index], &text_ptr, &num_text)) < 1) { g_debug ("Calling png_get_text() returned %d (< 1)", found); continue; } for (i = 0; i < num_text; i++) { if (!text_ptr[i].key || !text_ptr[i].text || text_ptr[i].text[0] == '\0') { continue; } #if defined(HAVE_EXEMPI) && defined(PNG_iTXt_SUPPORTED) if (g_strcmp0 ("XML:com.adobe.xmp", text_ptr[i].key) == 0) { /* ATM tracker_extract_xmp_read supports setting xd * multiple times, keep it that way as here it's * theoretically possible that the function gets * called multiple times */ xd = tracker_xmp_new (text_ptr[i].text, text_ptr[i].itxt_length, uri); continue; } if (g_strcmp0 ("Raw profile type xmp", text_ptr[i].key) == 0) { gchar *xmp_buffer; guint xmp_buffer_length = 0; guint input_len; if (text_ptr[i].text_length) { input_len = text_ptr[i].text_length; } else { input_len = text_ptr[i].itxt_length; } xmp_buffer = raw_profile_new (text_ptr[i].text, input_len, &xmp_buffer_length); if (xmp_buffer) { xd = tracker_xmp_new (xmp_buffer, xmp_buffer_length, uri); } g_free (xmp_buffer); continue; } #endif /*HAVE_EXEMPI && PNG_iTXt_SUPPORTED */ #if defined(HAVE_LIBEXIF) && defined(PNG_iTXt_SUPPORTED) if (g_strcmp0 ("Raw profile type exif", text_ptr[i].key) == 0) { gchar *exif_buffer; guint exif_buffer_length = 0; guint input_len; if (text_ptr[i].text_length) { input_len = text_ptr[i].text_length; } else { input_len = text_ptr[i].itxt_length; } exif_buffer = raw_profile_new (text_ptr[i].text, input_len, &exif_buffer_length); if (exif_buffer) { ed = tracker_exif_new (exif_buffer, exif_buffer_length, uri); } g_free (exif_buffer); continue; } #endif /* HAVE_LIBEXIF && PNG_iTXt_SUPPORTED */ if (g_strcmp0 (text_ptr[i].key, "Author") == 0) { pd.author = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Creator") == 0) { pd.creator = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Description") == 0) { pd.description = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Comment") == 0) { pd.comment = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Copyright") == 0) { pd.copyright = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Creation Time") == 0) { pd.creation_time = rfc1123_to_iso8601_date (text_ptr[i].text); continue; } if (g_strcmp0 (text_ptr[i].key, "Title") == 0) { pd.title = text_ptr[i].text; continue; } if (g_strcmp0 (text_ptr[i].key, "Disclaimer") == 0) { pd.disclaimer = text_ptr[i].text; continue; } if (g_strcmp0(text_ptr[i].key, "Software") == 0) { pd.software = text_ptr[i].text; continue; } } } if (!ed) { ed = g_new0 (TrackerExifData, 1); } if (!xd) { xd = g_new0 (TrackerXmpData, 1); } md.creator = tracker_coalesce_strip (3, xd->creator, pd.creator, pd.author); md.title = tracker_coalesce_strip (5, xd->title, pd.title, ed->document_name, xd->title2, xd->pdf_title); md.copyright = tracker_coalesce_strip (3, xd->rights, pd.copyright, ed->copyright); md.license = tracker_coalesce_strip (2, xd->license, pd.disclaimer); md.description = tracker_coalesce_strip (3, xd->description, pd.description, ed->description); md.date = tracker_coalesce_strip (5, xd->date, xd->time_original, pd.creation_time, ed->time, ed->time_original); md.comment = tracker_coalesce_strip (2, pd.comment, ed->user_comment); md.artist = tracker_coalesce_strip (3, xd->artist, ed->artist, xd->contributor); md.orientation = tracker_coalesce_strip (2, xd->orientation, ed->orientation); md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); md.make = tracker_coalesce_strip (2, xd->make, ed->make); md.model = tracker_coalesce_strip (2, xd->model, ed->model); keywords = g_ptr_array_new (); if (md.comment) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, md.comment); } if (md.license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, md.license); } /* TODO: add ontology and store this ed->software */ if (md.creator) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } tracker_guarantee_date_from_file_mtime (metadata, "nie:contentCreated", md.date, uri); if (md.description) { tracker_sparql_builder_predicate (metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (metadata, md.description); } if (md.copyright) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, md.copyright); } tracker_guarantee_title_from_file (metadata, "nie:title", md.title, uri, NULL); if (md.make || md.model) { gchar *equip_uri; equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", md.make ? md.make : "", md.model ? md.model : ""); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, equip_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nfo:Equipment"); if (md.make) { tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer"); tracker_sparql_builder_object_unvalidated (preupdate, md.make); } if (md.model) { tracker_sparql_builder_predicate (preupdate, "nfo:model"); tracker_sparql_builder_object_unvalidated (preupdate, md.model); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nfo:equipment"); tracker_sparql_builder_object_iri (metadata, equip_uri); g_free (equip_uri); } if (md.artist) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.artist); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.artist); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:contributor"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (md.orientation) { tracker_sparql_builder_predicate (metadata, "nfo:orientation"); tracker_sparql_builder_object_unvalidated (metadata, md.orientation); } if (md.exposure_time) { tracker_sparql_builder_predicate (metadata, "nmm:exposureTime"); tracker_sparql_builder_object_unvalidated (metadata, md.exposure_time); } if (md.iso_speed_ratings) { tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed"); tracker_sparql_builder_object_unvalidated (metadata, md.iso_speed_ratings); } if (md.white_balance) { tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance"); tracker_sparql_builder_object_unvalidated (metadata, md.white_balance); } if (md.fnumber) { tracker_sparql_builder_predicate (metadata, "nmm:fnumber"); tracker_sparql_builder_object_unvalidated (metadata, md.fnumber); } if (md.flash) { tracker_sparql_builder_predicate (metadata, "nmm:flash"); tracker_sparql_builder_object_unvalidated (metadata, md.flash); } if (md.focal_length) { tracker_sparql_builder_predicate (metadata, "nmm:focalLength"); tracker_sparql_builder_object_unvalidated (metadata, md.focal_length); } if (md.metering_mode) { tracker_sparql_builder_predicate (metadata, "nmm:meteringMode"); tracker_sparql_builder_object_unvalidated (metadata, md.metering_mode); } if (xd->keywords) { tracker_keywords_parse (keywords, xd->keywords); } if (xd->pdf_keywords) { tracker_keywords_parse (keywords, xd->pdf_keywords); } if (xd->rating) { tracker_sparql_builder_predicate (metadata, "nao:numericRating"); tracker_sparql_builder_object_unvalidated (metadata, xd->rating); } if (xd->subject) { tracker_keywords_parse (keywords, xd->subject); } if (xd->publisher) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->publisher); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, xd->publisher); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (xd->type) { tracker_sparql_builder_predicate (metadata, "dc:type"); tracker_sparql_builder_object_unvalidated (metadata, xd->type); } if (xd->format) { tracker_sparql_builder_predicate (metadata, "dc:format"); tracker_sparql_builder_object_unvalidated (metadata, xd->format); } if (xd->identifier) { tracker_sparql_builder_predicate (metadata, "dc:identifier"); tracker_sparql_builder_object_unvalidated (metadata, xd->identifier); } if (xd->source) { tracker_sparql_builder_predicate (metadata, "dc:source"); tracker_sparql_builder_object_unvalidated (metadata, xd->source); } if (xd->language) { tracker_sparql_builder_predicate (metadata, "dc:language"); tracker_sparql_builder_object_unvalidated (metadata, xd->language); } if (xd->relation) { tracker_sparql_builder_predicate (metadata, "dc:relation"); tracker_sparql_builder_object_unvalidated (metadata, xd->relation); } if (xd->coverage) { tracker_sparql_builder_predicate (metadata, "dc:coverage"); tracker_sparql_builder_object_unvalidated (metadata, xd->coverage); } if (xd->address || xd->state || xd->country || xd->city || xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:location"); tracker_sparql_builder_object_blank_open (metadata); /* GeoLocation */ tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "slo:GeoLocation"); if (xd->address || xd->state || xd->country || xd->city) { gchar *addruri; addruri = tracker_sparql_get_uuid_urn (); tracker_sparql_builder_predicate (metadata, "slo:postalAddress"); tracker_sparql_builder_object_iri (metadata, addruri); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, addruri); g_free (addruri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:PostalAddress"); if (xd->address) { tracker_sparql_builder_predicate (preupdate, "nco:streetAddress"); tracker_sparql_builder_object_unvalidated (preupdate, xd->address); } if (xd->state) { tracker_sparql_builder_predicate (preupdate, "nco:region"); tracker_sparql_builder_object_unvalidated (preupdate, xd->state); } if (xd->city) { tracker_sparql_builder_predicate (preupdate, "nco:locality"); tracker_sparql_builder_object_unvalidated (preupdate, xd->city); } if (xd->country) { tracker_sparql_builder_predicate (preupdate, "nco:country"); tracker_sparql_builder_object_unvalidated (preupdate, xd->country); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (xd->gps_altitude) { tracker_sparql_builder_predicate (metadata, "slo:altitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_altitude); } if (xd->gps_latitude) { tracker_sparql_builder_predicate (metadata, "slo:latitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_latitude); } if (xd->gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:longitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_longitude); } tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */ } if (xd->gps_direction) { tracker_sparql_builder_predicate (metadata, "nfo:heading"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_direction); } if (ed->x_resolution) { gdouble value; value = ed->resolution_unit != 3 ? g_strtod (ed->x_resolution, NULL) : g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; tracker_sparql_builder_predicate (metadata, "nfo:horizontalResolution"); tracker_sparql_builder_object_double (metadata, value); } if (ed->y_resolution) { gdouble value; value = ed->resolution_unit != 3 ? g_strtod (ed->y_resolution, NULL) : g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; tracker_sparql_builder_predicate (metadata, "nfo:verticalResolution"); tracker_sparql_builder_object_double (metadata, value); } if (xd->regions) { tracker_xmp_apply_regions (preupdate, metadata, graph, xd); } for (i = 0; i < keywords->len; i++) { gchar *p, *escaped, *var; p = g_ptr_array_index (keywords, i); escaped = tracker_sparql_escape_string (p); var = g_strdup_printf ("tag%d", i + 1); /* ensure tag with specified label exists */ tracker_sparql_builder_append (preupdate, "INSERT { "); if (graph) { tracker_sparql_builder_append (preupdate, "GRAPH <"); tracker_sparql_builder_append (preupdate, graph); tracker_sparql_builder_append (preupdate, "> { "); } tracker_sparql_builder_append (preupdate, "_:tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\""); if (graph) { tracker_sparql_builder_append (preupdate, " } "); } tracker_sparql_builder_append (preupdate, " }\n"); tracker_sparql_builder_append (preupdate, "WHERE { FILTER (NOT EXISTS { " "?tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\" }) }\n"); /* associate file with tag */ tracker_sparql_builder_predicate (metadata, "nao:hasTag"); tracker_sparql_builder_object_variable (metadata, var); g_string_append_printf (where, "?%s a nao:Tag ; nao:prefLabel \"%s\" .\n", var, escaped); g_free (var); g_free (escaped); g_free (p); } g_ptr_array_free (keywords, TRUE); if (g_strcmp0(pd.software, "gnome-screenshot") == 0) { tracker_sparql_builder_predicate (metadata, "nie:isPartOf"); tracker_sparql_builder_object (metadata, "nfo:image-category-screenshot"); } tracker_exif_free (ed); tracker_xmp_free (xd); g_free (pd.creation_time); }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info_) { /* NOTE: This function has to exist, tracker-extract checks * the symbole table for this function and if it doesn't * exist, the module is not loaded to be used as an extractor. */ /* File information */ GFile *file; GError *error = NULL; gchar *filename; OsinfoLoader *loader = NULL; OsinfoMedia *media; OsinfoDb *db; OsinfoOs *os; OsinfoOsVariantList *variants; /* Data input */ gboolean bootable; const gchar *id; const gchar *name; TrackerSparqlBuilder *metadata; metadata = tracker_extract_info_get_metadata_builder (info_); file = tracker_extract_info_get_file (info_); filename = g_file_get_path (file); media = osinfo_media_create_from_location (filename, NULL, &error); if (error != NULL) { if (error->code != OSINFO_MEDIA_ERROR_NOT_BOOTABLE) { g_message ("Could not extract iso info from '%s': %s", filename, error->message); g_free (filename); g_error_free (error); return FALSE; } bootable = FALSE; goto no_os; } else { bootable = TRUE; } g_free (filename); loader = osinfo_loader_new (); osinfo_loader_process_default_path (loader, &error); if (error != NULL) { g_message ("Error loading libosinfo OS data: %s", error->message); g_error_free (error); goto no_os; } g_warn_if_fail (media != NULL); g_warn_if_fail (loader != NULL); db = osinfo_loader_get_db (loader); osinfo_db_identify_media (db, media); os = osinfo_media_get_os (media); if (os == NULL) goto unknown_os; tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:FilesystemImage"); variants = osinfo_media_get_os_variants (media); if (osinfo_list_get_length (OSINFO_LIST (variants)) > 0) { OsinfoEntity *variant; /* FIXME: Assuming first variant from multivariant medias. */ variant = osinfo_list_get_nth (OSINFO_LIST (variants), 0); name = osinfo_os_variant_get_name (OSINFO_OS_VARIANT (variant)); } else { name = osinfo_product_get_name (OSINFO_PRODUCT (os)); } if (name != NULL) { tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_string (metadata, name); } if (osinfo_media_get_live (media)) { tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:OperatingSystem"); } if (osinfo_media_get_installer (media)) { tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "osinfo:Installer"); } tracker_sparql_builder_predicate (metadata, "nfo:isBootable"); tracker_sparql_builder_object_boolean (metadata, bootable); id = osinfo_entity_get_id (OSINFO_ENTITY (os)); if (id != NULL) { tracker_sparql_builder_predicate (metadata, "osinfo:id"); tracker_sparql_builder_object_string (metadata, id); } id = osinfo_entity_get_id (OSINFO_ENTITY (media)); if (id != NULL) { tracker_sparql_builder_predicate (metadata, "osinfo:mediaId"); tracker_sparql_builder_object_string (metadata, id); } g_object_unref (G_OBJECT (media)); g_object_unref (G_OBJECT (loader)); return TRUE; unknown_os: name = osinfo_media_get_volume_id (media); if (name != NULL) { gchar *stripped = g_strdup (name); g_strstrip (stripped); tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_string (metadata, stripped); g_free (stripped); } no_os: if (media != NULL) { g_object_unref (G_OBJECT (media)); } if (loader != NULL) { g_object_unref (G_OBJECT (loader)); } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:FilesystemImage"); tracker_sparql_builder_predicate (metadata, "nfo:isBootable"); tracker_sparql_builder_object_boolean (metadata, bootable); return TRUE; }
static void process_desktop_file (ProcessApplicationData *data, GFileInfo *file_info, GError **error) { TrackerSparqlBuilder *sparql; GKeyFile *key_file; gchar *name = NULL; gchar *path; gchar *type; gchar *filename; gchar *uri = NULL; GStrv cats; gsize cats_len; gboolean is_software = TRUE; const gchar *parent_urn; gchar *lang; #ifdef HAVE_MEEGOTOUCH gchar *logical_id = NULL; gchar *translation_catalog = NULL; #endif /* HAVE_MEEGOTOUCH */ sparql = data->sparql; key_file = data->key_file; type = data->type; path = g_file_get_path (data->file); /* Retrieve LANG locale setup */ lang = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); /* Try to get the categories with our desired LANG locale... */ cats = g_key_file_get_locale_string_list (key_file, GROUP_DESKTOP_ENTRY, "Categories", lang, &cats_len, NULL); if (!cats) { /* If our desired locale failed, use the list of LANG locales prepared by GLib * (will return untranslated string if none of the locales available) */ cats = g_key_file_get_locale_string_list (key_file, GROUP_DESKTOP_ENTRY, "Categories", NULL, &cats_len, NULL); } /* NOTE: We sanitize categories later on when iterating them */ #ifdef HAVE_MEEGOTOUCH /* If defined, start with the logical strings */ logical_id = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "X-MeeGo-Logical-Id", NULL); translation_catalog = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "X-MeeGo-Translation-Catalog", NULL); if (logical_id && translation_catalog) { name = tracker_meego_translate (translation_catalog, logical_id); } g_free (logical_id); g_free (translation_catalog); #endif /* HAVE_MEEGOTOUCH */ if (!name) { /* Try to get the name with our desired LANG locale... */ name = g_key_file_get_locale_string (key_file, GROUP_DESKTOP_ENTRY, "Name", lang, NULL); if (!name) { /* If our desired locale failed, use the list of LANG locales prepared by GLib * (will return untranslated string if none of the locales available) */ name = g_key_file_get_locale_string (key_file, GROUP_DESKTOP_ENTRY, "Name", NULL, NULL); } } /* Sanitize name */ if (name) { g_strstrip (name); } if (name && g_ascii_strcasecmp (type, "Directory") == 0) { gchar *canonical_uri = tracker_sparql_escape_uri_printf (SOFTWARE_CATEGORY_URN_PREFIX "%s", path); gchar *icon = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "Icon", NULL); uri = canonical_uri; tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); if (icon) { gchar *escaped_icon; gchar *icon_uri; /* Sanitize icon */ g_strstrip (icon); escaped_icon = g_uri_escape_string (icon, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE); icon_uri = g_strdup_printf (THEME_ICON_URN_PREFIX "%s", escaped_icon); tracker_sparql_builder_subject_iri (sparql, icon_uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:Image"); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "nfo:softwareCategoryIcon"); tracker_sparql_builder_object_iri (sparql, icon_uri); g_free (icon_uri); g_free (escaped_icon); g_free (icon); } is_software = FALSE; } else if (name && g_ascii_strcasecmp (type, "Application") == 0) { uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, APPLICATION_DATASOURCE_URN); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nie:DataSource"); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareApplication"); tracker_sparql_builder_object (sparql, "nie:DataObject"); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); } else if (name && g_ascii_strcasecmp (type, "Link") == 0) { gchar *url = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "URL", NULL); if (url) { uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:Bookmark"); tracker_sparql_builder_predicate (sparql, "nfo:bookmarks"); tracker_sparql_builder_object_iri (sparql, url); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); is_software = FALSE; g_free (url); } else { g_warning ("Invalid desktop file: '%s'", uri); g_warning (" Type 'Link' requires a URL"); } #ifdef HAVE_MEEGOTOUCH } else if (name && g_ascii_strcasecmp (type, "ControlPanelApplet") == 0) { /* Special case control panel applets */ /* The URI of the InformationElement should be a UUID URN */ uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, APPLET_DATASOURCE_URN); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nie:DataSource"); /* TODO This is atm specific for Maemo */ tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "maemo:ControlPanelApplet"); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLET_DATASOURCE_URN); /* This matches SomeApplet as Type= */ } else if (name && g_str_has_suffix (type, "Applet")) { /* The URI of the InformationElement should be a UUID URN */ uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, APPLET_DATASOURCE_URN); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nie:DataSource"); /* TODO This is atm specific for Maemo */ tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "maemo:SoftwareApplet"); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLET_DATASOURCE_URN); } else if (name && g_ascii_strcasecmp (type, "DUIApplication") == 0) { uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, APPLICATION_DATASOURCE_URN); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nie:DataSource"); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareApplication"); tracker_sparql_builder_object (sparql, "nie:DataObject"); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); #endif /* HAVE_MEEGOTOUCH */ } else { /* Invalid type, all valid types are already listed above */ uri = g_file_get_uri (data->file); tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_iri (sparql, APPLICATION_DATASOURCE_URN); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nie:DataSource"); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareApplication"); tracker_sparql_builder_object (sparql, "nie:DataObject"); tracker_sparql_builder_predicate (sparql, "nie:dataSource"); tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); if (name) { /* If we got a name, then the issue comes from the type. * As we're defaulting to Application here, we just g_debug() the problem. */ g_debug ("Invalid desktop file: '%s'", uri); g_debug (" Type '%s' is not part of the desktop file specification (expected 'Application', 'Link' or 'Directory')", type); g_debug (" Defaulting to 'Application'"); } else { /* If we didn't get a name, the problem is more severe as we don't default it * to anything, so we g_warning() it. */ g_warning ("Invalid desktop file: '%s'", uri); #ifdef HAVE_MEEGOTOUCH g_warning (" Couldn't get name, missing or wrong key (X-MeeGo-Logical-Id, X-MeeGo-Translation-Catalog or Name)"); #else g_warning (" Couldn't get name, missing key (Name)"); #endif } } if (sparql && uri) { gchar *desktop_file_uri; tracker_sparql_builder_predicate (sparql, "a"); if (is_software) { tracker_sparql_builder_object (sparql, "nfo:Executable"); } tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); tracker_sparql_builder_object (sparql, "nie:DataObject"); /* Apparently this gets added by the file-module ATM tracker_sparql_builder_predicate (sparql, "tracker:available"); tracker_sparql_builder_object_boolean (sparql, TRUE); */ /* We should always always have a proper name if the desktop file is correct * w.r.t to the Meego or Freedesktop specs, but sometimes this is not true, * so instead of passing wrong stuff to the SPARQL builder, we avoid it. * If we don't have a proper name, we already warned it before. */ if (name) { tracker_sparql_builder_predicate (sparql, "nie:title"); tracker_sparql_builder_object_string (sparql, name); } if (is_software) { gchar *icon; insert_data_from_desktop_file (sparql, uri, TRACKER_PREFIX_NIE "comment", key_file, "Comment", lang); insert_data_from_desktop_file (sparql, uri, TRACKER_PREFIX_NFO "softwareCmdLine", key_file, "Exec", lang); icon = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "Icon", NULL); if (icon) { gchar *escaped_icon; gchar *icon_uri; /* Sanitize icon */ g_strstrip (icon); escaped_icon = g_uri_escape_string (icon, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE); icon_uri = g_strdup_printf (THEME_ICON_URN_PREFIX "%s", escaped_icon); tracker_sparql_builder_subject_iri (sparql, icon_uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:Image"); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "nfo:softwareIcon"); tracker_sparql_builder_object_iri (sparql, icon_uri); g_free (icon_uri); g_free (escaped_icon); g_free (icon); } } if (cats) { gsize i; for (i = 0 ; cats[i] && i < cats_len ; i++) { gchar *cat_uri; gchar *cat; cat = cats[i]; if (!cat) { continue; } /* Sanitize category */ g_strstrip (cat); cat_uri = tracker_sparql_escape_uri_printf (SOFTWARE_CATEGORY_URN_PREFIX "%s", cat); /* There are also .desktop * files that describe these categories, but we can handle * preemptively creating them if we visit a app .desktop * file that mentions one that we don't yet know about */ tracker_sparql_builder_subject_iri (sparql, cat_uri); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); tracker_sparql_builder_predicate (sparql, "nie:title"); tracker_sparql_builder_object_string (sparql, cat); tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "nie:isLogicalPartOf"); tracker_sparql_builder_object_iri (sparql, cat_uri); g_free (cat_uri); } } filename = g_filename_display_basename (path); tracker_sparql_builder_predicate (sparql, "nfo:fileName"); tracker_sparql_builder_object_string (sparql, filename); g_free (filename); /* The URL of the DataObject */ desktop_file_uri = g_file_get_uri (data->file); tracker_sparql_builder_predicate (sparql, "nie:url"); tracker_sparql_builder_object_string (sparql, desktop_file_uri); /* Laying the link between the IE and the DO */ tracker_sparql_builder_subject_iri (sparql, uri); tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); tracker_sparql_builder_object_iri (sparql, desktop_file_uri); g_free (desktop_file_uri); } if (file_info) { guint64 time; time = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); tracker_sparql_builder_object_date (sparql, (time_t *) &time); } parent_urn = tracker_miner_fs_get_parent_urn (TRACKER_MINER_FS (data->miner), data->file); if (parent_urn) { tracker_sparql_builder_predicate (sparql, "nfo:belongsToContainer"); tracker_sparql_builder_object_iri (sparql, parent_urn); } tracker_sparql_builder_insert_close (sparql); g_strfreev (cats); g_free (uri); g_free (path); g_free (name); g_free (lang); }
static void opf_xml_text_handler (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { OPFData *data = user_data; switch (data->element) { case OPF_TAG_TYPE_PUBLISHER: if (data->has_publisher) { g_warning ("Avoiding additional publisher (%s) in EPUB '%s'", text, data->uri); } else { data->has_publisher = TRUE; tracker_sparql_builder_predicate (data->metadata, "nco:publisher"); tracker_sparql_builder_object_blank_open (data->metadata); tracker_sparql_builder_predicate (data->metadata, "a"); tracker_sparql_builder_object (data->metadata, "nco:Contact"); tracker_sparql_builder_predicate (data->metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (data->metadata, text); tracker_sparql_builder_object_blank_close (data->metadata); } break; case OPF_TAG_TYPE_AUTHOR: case OPF_TAG_TYPE_EDITOR: case OPF_TAG_TYPE_ILLUSTRATOR: case OPF_TAG_TYPE_CONTRIBUTOR: { gchar *fname, *gname, *oname; const gchar *fullname = NULL; gchar *role_uri = NULL; const gchar *role_str = NULL; gint i, j = 0, len; fname = NULL; gname = NULL; oname = NULL; /* parse name. may not work for dissimilar cultures. */ if (data->savedstring != NULL) { fullname = data->savedstring; /* <family name>, <given name> <other name> */ g_debug ("Parsing 'opf:file-as' attribute:'%s'", data->savedstring); len = strlen (data->savedstring); for (i = 0; i < len; i++) { if (data->savedstring[i] == ',') { fname = g_strndup (data->savedstring, i); g_debug ("Found family name:'%s'", fname); for (; data->savedstring[i] == ',' || data->savedstring[i] == ' '; i++); j = i; break; } } if (i == len) { fname = g_strdup (data->savedstring); g_debug ("Found only one name"); } else { for (; i <= len; i++) { if (i == len || data->savedstring[i] == ' ') { gname = g_strndup (data->savedstring + j, i - j); g_debug ("Found given name:'%s'", gname); for (; data->savedstring[i] == ',' || data->savedstring[i] == ' '; i++); if (i != len) { oname = g_strdup (data->savedstring + i); g_debug ("Found other name:'%s'", oname); } break; } } } } else { fullname = text; /* <given name> <other name> <family name> */ g_debug ("Parsing name, no 'opf:file-as' found: '%s'", text); len = strlen (text); for (i = 0; i < len; i++) { if (text[i] == ' ') { gname = g_strndup (text, i); g_debug ("Found given name:'%s'", gname); j = i + 1; break; } } if (j == 0) { fname = g_strdup (data->savedstring); g_debug ("Found only one name:'%s'", fname); } else { for (i = len - 1; i >= j - 1; i--) { if (text[i] == ' ') { fname = g_strdup (text + i + 1); g_debug ("Found family name:'%s'", fname); if (i > j) { oname = g_strndup (text + j, i - j); g_debug ("Found other name:'%s'", oname); } break; } } } } /* Role details */ role_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", fullname); if (data->element == OPF_TAG_TYPE_AUTHOR) { role_str = "nco:creator"; } else if (data->element == OPF_TAG_TYPE_EDITOR && !data->has_publisher) { /* Should this be nco:contributor ? * 'Editor' is a bit vague here. */ role_str = "nco:publisher"; } else if (data->element == OPF_TAG_TYPE_ILLUSTRATOR) { /* There is no illustrator class, using contributor */ role_str = "nco:contributor"; } else { g_assert ("Unknown role"); } if (role_uri) { tracker_sparql_builder_insert_open (data->preupdate, NULL); if (data->graph) { tracker_sparql_builder_graph_open (data->preupdate, data->graph); } tracker_sparql_builder_subject_iri (data->preupdate, role_uri); tracker_sparql_builder_predicate (data->preupdate, "a"); tracker_sparql_builder_object (data->preupdate, "nmm:Artist"); tracker_sparql_builder_predicate (data->preupdate, "nmm:artistName"); tracker_sparql_builder_object_unvalidated (data->preupdate, fullname); if (data->graph) { tracker_sparql_builder_graph_close (data->preupdate); } tracker_sparql_builder_insert_close (data->preupdate); } /* Creator contact details */ tracker_sparql_builder_predicate (data->metadata, "nco:creator"); tracker_sparql_builder_object_blank_open (data->metadata); tracker_sparql_builder_predicate (data->metadata, "a"); tracker_sparql_builder_object (data->metadata, "nco:PersonContact"); tracker_sparql_builder_predicate (data->metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (data->metadata, fullname); if (fname) { tracker_sparql_builder_predicate (data->metadata, "nco:nameFamily"); tracker_sparql_builder_object_unvalidated (data->metadata, fname); g_free (fname); } if (gname) { tracker_sparql_builder_predicate (data->metadata, "nco:nameGiven"); tracker_sparql_builder_object_unvalidated (data->metadata, gname); g_free (gname); } if (oname) { tracker_sparql_builder_predicate (data->metadata, "nco:nameAdditional"); tracker_sparql_builder_object_unvalidated (data->metadata, oname); g_free (oname); } if (role_uri) { tracker_sparql_builder_predicate (data->metadata, role_str); tracker_sparql_builder_object_iri (data->metadata, role_uri); g_free (role_uri); } tracker_sparql_builder_object_blank_close (data->metadata); break; } case OPF_TAG_TYPE_TITLE: if (data->has_title) { g_warning ("Avoiding additional title (%s) in EPUB '%s'", text, data->uri); } else { data->has_title = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (data->metadata, text); } break; case OPF_TAG_TYPE_CREATED: { if (data->has_content_created) { g_warning ("Avoiding additional creation time (%s) in EPUB '%s'", text, data->uri); } else { gchar *date = tracker_date_guess (text); if (date) { data->has_content_created = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:contentCreated"); tracker_sparql_builder_object_unvalidated (data->metadata, date); g_free (date); } else { g_warning ("Could not parse creation time (%s) in EPUB '%s'", text, data->uri); } } break; } case OPF_TAG_TYPE_LANGUAGE: if (data->has_language) { g_warning ("Avoiding additional language (%s) in EPUB '%s'", text, data->uri); } else { data->has_language = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:language"); tracker_sparql_builder_object_unvalidated (data->metadata, text); } break; case OPF_TAG_TYPE_SUBJECT: if (data->has_subject) { g_warning ("Avoiding additional subject (%s) in EPUB '%s'", text, data->uri); } else { data->has_subject = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:subject"); tracker_sparql_builder_object_unvalidated (data->metadata, text); } break; case OPF_TAG_TYPE_DESCRIPTION: if (data->has_description) { g_warning ("Avoiding additional description (%s) in EPUB '%s'", text, data->uri); } else { data->has_description = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (data->metadata, text); } break; case OPF_TAG_TYPE_UUID: case OPF_TAG_TYPE_ISBN: if (data->has_identifier) { g_warning ("Avoiding additional identifier (%s) in EPUB '%s'", text, data->uri); } else { data->has_identifier = TRUE; tracker_sparql_builder_predicate (data->metadata, "nie:identifier"); tracker_sparql_builder_object_unvalidated (data->metadata, text); } break; /* case OPF_TAG_TYPE_RATING: */ case OPF_TAG_TYPE_UNKNOWN: default: break; } opf_data_clear_saved_string (data); }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *preupdate, *metadata; VorbisData vd = { 0 }; MergeData md = { 0 }; FILE *f; gchar *filename; OggVorbis_File vf; vorbis_comment *comment; vorbis_info *vi; unsigned int bitrate; gint time; GFile *file; const gchar *graph; file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); f = tracker_file_open (filename); g_free (filename); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); if (!f) { return FALSE; } if (ov_open (f, &vf, NULL, 0) < 0) { tracker_file_close (f, FALSE); return FALSE; } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:MusicPiece"); tracker_sparql_builder_object (metadata, "nfo:Audio"); if ((comment = ov_comment (&vf, -1)) != NULL) { gchar *date; vd.title = ogg_get_comment (comment, "title"); vd.artist = ogg_get_comment (comment, "artist"); vd.album = ogg_get_comment (comment, "album"); vd.album_artist = ogg_get_comment (comment, "albumartist"); vd.track_count = ogg_get_comment (comment, "trackcount"); vd.track_number = ogg_get_comment (comment, "tracknumber"); vd.disc_number = ogg_get_comment (comment, "DiscNo"); vd.performer = ogg_get_comment (comment, "Performer"); vd.track_gain = ogg_get_comment (comment, "TrackGain"); vd.track_peak_gain = ogg_get_comment (comment, "TrackPeakGain"); vd.album_gain = ogg_get_comment (comment, "AlbumGain"); vd.album_peak_gain = ogg_get_comment (comment, "AlbumPeakGain"); date = ogg_get_comment (comment, "date"); vd.date = tracker_date_guess (date); g_free (date); vd.comment = ogg_get_comment (comment, "comment"); vd.genre = ogg_get_comment (comment, "genre"); vd.codec = ogg_get_comment (comment, "Codec"); vd.codec_version = ogg_get_comment (comment, "CodecVersion"); vd.sample_rate = ogg_get_comment (comment, "SampleRate"); vd.channels = ogg_get_comment (comment, "Channels"); vd.mb_album_id = ogg_get_comment (comment, "MBAlbumID"); vd.mb_artist_id = ogg_get_comment (comment, "MBArtistID"); vd.mb_album_artist_id = ogg_get_comment (comment, "MBAlbumArtistID"); vd.mb_track_id = ogg_get_comment (comment, "MBTrackID"); vd.lyrics = ogg_get_comment (comment, "Lyrics"); vd.copyright = ogg_get_comment (comment, "Copyright"); vd.license = ogg_get_comment (comment, "License"); vd.organization = ogg_get_comment (comment, "Organization"); vd.location = ogg_get_comment (comment, "Location"); vd.publisher = ogg_get_comment (comment, "Publisher"); vorbis_comment_clear (comment); } md.creator = tracker_coalesce_strip (3, vd.artist, vd.album_artist, vd.performer); if (md.creator) { /* NOTE: This must be created before vd.album is evaluated */ md.creator_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, md.creator_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:Artist"); tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); tracker_sparql_builder_object_unvalidated (preupdate, md.creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nmm:performer"); tracker_sparql_builder_object_iri (metadata, md.creator_uri); } if (vd.album) { gchar *uri; if (vd.album_artist) { uri = tracker_sparql_escape_uri_printf ("urn:album:%s:%s", vd.album, vd.album_artist); } else { uri = tracker_sparql_escape_uri_printf ("urn:album:%s", vd.album); } gchar *album_disc_uri; tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum"); /* FIXME: nmm:albumTitle is now deprecated * tracker_sparql_builder_predicate (preupdate, "nie:title"); */ tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle"); tracker_sparql_builder_object_unvalidated (preupdate, vd.album); if (md.creator_uri) { tracker_sparql_builder_predicate (preupdate, "nmm:albumArtist"); tracker_sparql_builder_object_iri (preupdate, md.creator_uri); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); if (vd.track_count) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_unvalidated (preupdate, vd.track_count); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (vd.album_gain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_double (preupdate, atof (vd.album_gain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (vd.album_peak_gain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_double (preupdate, atof (vd.album_peak_gain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (vd.album_artist) { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:%s:Disc%d", vd.album, vd.album_artist, vd.disc_number ? atoi(vd.disc_number) : 1); } else { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", vd.album, vd.disc_number ? atoi(vd.disc_number) : 1); } tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc"); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_int64 (preupdate, vd.disc_number ? atoi (vd.disc_number) : 1); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_iri (preupdate, uri); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc"); tracker_sparql_builder_object_iri (metadata, album_disc_uri); g_free (album_disc_uri); g_free (vd.album); tracker_sparql_builder_predicate (metadata, "nmm:musicAlbum"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } g_free (vd.track_count); g_free (vd.album_peak_gain); g_free (vd.album_gain); g_free (vd.disc_number); if (vd.title) { tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (metadata, vd.title); g_free (vd.title); } if (vd.track_number) { tracker_sparql_builder_predicate (metadata, "nmm:trackNumber"); tracker_sparql_builder_object_unvalidated (metadata, vd.track_number); g_free (vd.track_number); } if (vd.track_gain) { /* TODO */ g_free (vd.track_gain); } if (vd.track_peak_gain) { /* TODO */ g_free (vd.track_peak_gain); } if (vd.comment) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, vd.comment); g_free (vd.comment); } if (vd.date) { tracker_sparql_builder_predicate (metadata, "nie:contentCreated"); tracker_sparql_builder_object_unvalidated (metadata, vd.date); g_free (vd.date); } if (vd.genre) { tracker_sparql_builder_predicate (metadata, "nfo:genre"); tracker_sparql_builder_object_unvalidated (metadata, vd.genre); g_free (vd.genre); } if (vd.codec) { tracker_sparql_builder_predicate (metadata, "nfo:codec"); tracker_sparql_builder_object_unvalidated (metadata, vd.codec); g_free (vd.codec); } if (vd.codec_version) { /* TODO */ g_free (vd.codec_version); } if (vd.sample_rate) { tracker_sparql_builder_predicate (metadata, "nfo:sampleRate"); tracker_sparql_builder_object_unvalidated (metadata, vd.sample_rate); g_free (vd.sample_rate); } if (vd.channels) { tracker_sparql_builder_predicate (metadata, "nfo:channels"); tracker_sparql_builder_object_unvalidated (metadata, vd.channels); g_free (vd.channels); } if (vd.mb_album_id) { /* TODO */ g_free (vd.mb_album_id); } if (vd.mb_artist_id) { /* TODO */ g_free (vd.mb_artist_id); } if (vd.mb_album_artist_id) { /* TODO */ g_free (vd.mb_album_artist_id); } if (vd.mb_track_id) { /* TODO */ g_free (vd.mb_track_id); } if (vd.lyrics) { tracker_sparql_builder_predicate (metadata, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (metadata, vd.lyrics); g_free (vd.lyrics); } if (vd.copyright) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, vd.copyright); g_free (vd.copyright); } if (vd.license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, vd.license); g_free (vd.license); } if (vd.organization) { /* TODO */ g_free (vd.organization); } if (vd.location) { /* TODO */ g_free (vd.location); } if (vd.publisher) { tracker_sparql_builder_predicate (metadata, "dc:publisher"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, vd.publisher); tracker_sparql_builder_object_blank_close (metadata); g_free (vd.publisher); } if ((vi = ov_info (&vf, 0)) != NULL ) { bitrate = vi->bitrate_nominal / 1000; tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate"); tracker_sparql_builder_object_int64 (metadata, (gint64) bitrate); } /* Duration */ if ((time = ov_time_total (&vf, -1)) != OV_EINVAL) { tracker_sparql_builder_predicate (metadata, "nfo:duration"); tracker_sparql_builder_object_int64 (metadata, (gint64) time); } g_free (vd.artist); g_free (vd.album_artist); g_free (vd.performer); g_free (md.creator_uri); #ifdef HAVE_POSIX_FADVISE posix_fadvise (fileno (f), 0, 0, POSIX_FADV_DONTNEED); #endif /* HAVE_POSIX_FADVISE */ /* NOTE: This calls fclose on the file */ ov_clear (&vf); return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { goffset size; FILE *f; png_structp png_ptr; png_infop info_ptr; png_infop end_ptr; png_bytepp row_pointers; guint row; png_uint_32 width, height; gint bit_depth, color_type; gint interlace_type, compression_type, filter_type; const gchar *dlna_profile, *dlna_mimetype, *graph; TrackerSparqlBuilder *preupdate, *metadata; gchar *filename, *uri; GString *where; GFile *file; file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); if (size < 64) { return FALSE; } f = tracker_file_open (filename); g_free (filename); if (!f) { return FALSE; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { tracker_file_close (f, FALSE); return FALSE; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); tracker_file_close (f, FALSE); return FALSE; } end_ptr = png_create_info_struct (png_ptr); if (!end_ptr) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); tracker_file_close (f, FALSE); return FALSE; } if (setjmp (png_jmpbuf (png_ptr))) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return FALSE; } png_init_io (png_ptr, f); png_read_info (png_ptr, info_ptr); if (!png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return FALSE; } /* Read the image. FIXME We should be able to skip this step and * just get the info from the end. This causes some errors atm. */ row_pointers = g_new0 (png_bytep, height); for (row = 0; row < height; row++) { row_pointers[row] = png_malloc (png_ptr, png_get_rowbytes (png_ptr,info_ptr)); } png_read_image (png_ptr, row_pointers); for (row = 0; row < height; row++) { png_free (png_ptr, row_pointers[row]); } g_free (row_pointers); png_read_end (png_ptr, end_ptr); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_object (metadata, "nmm:Photo"); uri = g_file_get_uri (file); where = g_string_new (""); read_metadata (preupdate, metadata, where, png_ptr, info_ptr, end_ptr, uri, graph); tracker_extract_info_set_where_clause (info, where->str); g_string_free (where, TRUE); g_free (uri); tracker_sparql_builder_predicate (metadata, "nfo:width"); tracker_sparql_builder_object_int64 (metadata, width); tracker_sparql_builder_predicate (metadata, "nfo:height"); tracker_sparql_builder_object_int64 (metadata, height); if (guess_dlna_profile (bit_depth, width, height, &dlna_profile, &dlna_mimetype)) { tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile"); tracker_sparql_builder_object_string (metadata, dlna_profile); tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime"); tracker_sparql_builder_object_string (metadata, dlna_mimetype); } png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { GFile *file; TrackerSparqlBuilder *metadata; TrackerSparqlBuilder *preupdate; const gchar *graph; gchar *absolute_file_path; gchar *uri; AVFormatContext *format = NULL; AVStream *audio_stream = NULL; AVStream *video_stream = NULL; int audio_stream_index; int video_stream_index; AVDictionaryEntry *tag = NULL; const char *title = NULL; av_register_all (); file = tracker_extract_info_get_file (info); metadata = tracker_extract_info_get_metadata_builder (info); preupdate = tracker_extract_info_get_preupdate_builder (info); graph = tracker_extract_info_get_graph (info); uri = g_file_get_uri (file); absolute_file_path = g_file_get_path (file); if (avformat_open_input (&format, absolute_file_path, NULL, NULL)) { g_free (absolute_file_path); g_free (uri); return FALSE; } g_free (absolute_file_path); avformat_find_stream_info (format, NULL); audio_stream_index = av_find_best_stream (format, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); if (audio_stream_index >= 0) { audio_stream = format->streams[audio_stream_index]; } video_stream_index = av_find_best_stream (format, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (video_stream_index >= 0) { video_stream = format->streams[video_stream_index]; } if (!audio_stream && !video_stream) { avformat_free_context (format); g_free (uri); return FALSE; } if (audio_stream) { if (audio_stream->codec->sample_rate > 0) { set_value_int64 (metadata, "nfo:sampleRate", audio_stream->codec->sample_rate); } if (audio_stream->codec->channels > 0) { set_value_int64 (metadata, "nfo:channels", audio_stream->codec->channels); } } if (video_stream) { tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:Video"); if (video_stream->codec->width > 0 && video_stream->codec->height > 0) { set_value_int64 (metadata, "nfo:width", video_stream->codec->width); set_value_int64 (metadata, "nfo:height", video_stream->codec->height); } if (video_stream->avg_frame_rate.num > 0) { gdouble frame_rate = (gdouble) video_stream->avg_frame_rate.num / video_stream->avg_frame_rate.den; set_value_double (metadata, "nfo:frameRate", frame_rate); } if (video_stream->duration > 0) { gint64 duration = av_rescale(video_stream->duration, video_stream->time_base.num, video_stream->time_base.den); set_value_int64 (metadata, "nfo:duration", duration); } if (video_stream->sample_aspect_ratio.num > 0) { gdouble aspect_ratio = (gdouble) video_stream->sample_aspect_ratio.num / video_stream->sample_aspect_ratio.den; set_value_double (metadata, "nfo:aspectRatio", aspect_ratio); } if (video_stream->nb_frames > 0) { set_value_int64 (metadata, "nfo:frameCount", video_stream->nb_frames); } if ((tag = av_dict_get (format->metadata, "synopsis", NULL, 0))) { set_value_string (metadata, "nmm:synopsis", tag->value); } if ((tag = av_dict_get (format->metadata, "episode_sort", NULL, 0))) { set_value_int64 (metadata, "nmm:episodeNumber", atoi(tag->value)); } if ((tag = av_dict_get (format->metadata, "season_number", NULL, 0))) { set_value_int64 (metadata, "nmm:season", atoi(tag->value)); } } else if (audio_stream) { const char *album_title = NULL; const char *album_artist = NULL; gchar *album_artist_uri = NULL; gchar *performer_uri = NULL; tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:MusicPiece"); tracker_sparql_builder_object (metadata, "nfo:Audio"); if (audio_stream->duration > 0) { gint64 duration = av_rescale(audio_stream->duration, audio_stream->time_base.num, audio_stream->time_base.den); set_value_int64 (metadata, "nfo:duration", duration); } if ((tag = find_tag (format, audio_stream, "track"))) { int track = atoi(tag->value); if (track > 0) { set_value_int64 (metadata, "nmm:trackNumber", track); } } if ((tag = find_tag (format, audio_stream, "album"))) { album_title = tag->value; } if (album_title && (tag = find_tag (format, audio_stream, "album_artist"))) { album_artist_uri = create_artist (preupdate, graph, tag->value); album_artist = tag->value; } if ((tag = find_tag (format, audio_stream, "artist"))) { performer_uri = create_artist (preupdate, graph, tag->value); if (!album_artist) { album_artist = tag->value; } } if (!performer_uri && (tag = find_tag (format, audio_stream, "performer"))) { performer_uri = create_artist (preupdate, graph, tag->value); if (!album_artist) { album_artist = tag->value; } } if (performer_uri) { set_value_iri (metadata, "nmm:performer", performer_uri); } else if (album_artist_uri) { set_value_iri (metadata, "nmm:performer", album_artist_uri); } if ((tag = find_tag (format, audio_stream, "composer"))) { gchar *composer_uri = create_artist (preupdate, graph, tag->value); set_value_iri (metadata, "nmm:composer", composer_uri); g_free(composer_uri); } if (album_title) { int disc = 1; gchar *disc_uri; gchar *album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", album_title); open_insert (preupdate, graph, album_uri, "nmm:MusicAlbum"); set_value_string (preupdate, "nmm:albumTitle", album_title); if (album_artist_uri) { set_value_iri (preupdate, "nmm:albumArtist", album_artist_uri); } else if (performer_uri) { set_value_iri (preupdate, "nmm:albumArtist", performer_uri); } close_insert (preupdate, graph); if ((tag = find_tag (format, audio_stream, "disc"))) { disc = atoi (tag->value); } disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", album_title, disc); delete_value (preupdate, disc_uri, "nmm:setNumber", "unknown"); delete_value (preupdate, disc_uri, "nmm:albumDiscAlbum", "unknown"); open_insert (preupdate, graph, disc_uri, "nmm:MusicAlbumDisc"); set_value_int64 (preupdate, "nmm:setNumber", disc); set_value_iri (preupdate, "nmm:albumDiscAlbum", album_uri); close_insert (preupdate, graph); set_value_iri (metadata, "nmm:musicAlbumDisc", disc_uri); set_value_iri (metadata, "nmm:musicAlbum", album_uri); g_free (disc_uri); g_free (album_uri); } #ifdef HAVE_LIBMEDIAART if (album_artist || album_title) { MediaArtProcess *media_art_process; GError *error = NULL; gboolean success; media_art_process = tracker_extract_info_get_media_art_process (info); success = media_art_process_file (media_art_process, MEDIA_ART_ALBUM, MEDIA_ART_PROCESS_FLAGS_NONE, file, album_artist, album_title, &error); if (!success || error) { g_warning ("Could not process media art for '%s', %s", uri, error ? error->message : "No error given"); g_clear_error (&error); } } #endif g_free(performer_uri); } if (format->bit_rate > 0) { set_value_int64 (metadata, "nfo:averageBitrate", format->bit_rate); } if ((tag = av_dict_get (format->metadata, "comment", NULL, 0))) { set_value_string (metadata, "nie:comment", tag->value); } if ((tag = av_dict_get (format->metadata, "copyright", NULL, 0))) { set_value_string (metadata, "nie:copyright", tag->value); } if ((tag = av_dict_get (format->metadata, "creation_time", NULL, 0))) { gchar *content_created = tracker_date_guess (tag->value); if (content_created) { set_value_string (metadata, "nie:contentCreated", content_created); g_free (content_created); } } if ((tag = av_dict_get (format->metadata, "description", NULL, 0))) { set_value_string (metadata, "nie:description", tag->value); } if ((tag = av_dict_get (format->metadata, "genre", NULL, 0))) { set_value_string (metadata, "nfo:genre", tag->value); } if ((tag = av_dict_get (format->metadata, "language", NULL, 0))) { set_value_string (metadata, "nfo:language", tag->value); } if ((tag = av_dict_get (format->metadata, "title", NULL, 0))) { title = tag->value; } tracker_guarantee_title_from_file (metadata, "nie:title", title, uri, NULL); g_free (uri); avformat_free_context (format); return TRUE; }
static inline void process_item (ProcessUserguideData *data, GFileInfo *file_info, gboolean is_dir, GError **error) { TrackerSparqlBuilder *sparql; gchar *uri; const gchar *mime_type; const gchar *urn; const gchar *parent_urn; gboolean is_iri; guint64 time_; sparql = data->sparql; uri = g_file_get_uri (data->file); mime_type = g_file_info_get_content_type (file_info); urn = get_file_urn (data->miner, data->file, &is_iri); tracker_sparql_builder_insert_silent_open (sparql, NULL); tracker_sparql_builder_graph_open (sparql, TRACKER_MINER_FS_GRAPH_URN); if (is_iri) { tracker_sparql_builder_subject_iri (sparql, urn); } else { tracker_sparql_builder_subject (sparql, urn); } tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); tracker_sparql_builder_object (sparql, "nie:InformationElement"); if (is_dir) { tracker_sparql_builder_object (sparql, "nfo:Folder"); } else { tracker_sparql_builder_object (sparql, "nfo:HelpDocument"); } parent_urn = tracker_miner_fs_get_parent_urn (TRACKER_MINER_FS (data->miner), data->file); if (parent_urn) { tracker_sparql_builder_predicate (sparql, "nfo:belongsToContainer"); tracker_sparql_builder_object_iri (sparql, parent_urn); } tracker_sparql_builder_predicate (sparql, "nfo:fileName"); tracker_sparql_builder_object_string (sparql, g_file_info_get_display_name (file_info)); tracker_sparql_builder_predicate (sparql, "nfo:fileSize"); tracker_sparql_builder_object_int64 (sparql, g_file_info_get_size (file_info)); time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); tracker_sparql_builder_object_date (sparql, (time_t *) &time_); time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS); tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed"); tracker_sparql_builder_object_date (sparql, (time_t *) &time_); /* Laying the link between the IE and the DO. We use IE = DO */ tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); if (is_iri) { tracker_sparql_builder_object_iri (sparql, urn); } else { tracker_sparql_builder_object (sparql, urn); } /* The URL of the DataObject (because IE = DO, this is correct) */ tracker_sparql_builder_predicate (sparql, "nie:url"); tracker_sparql_builder_object_string (sparql, uri); tracker_sparql_builder_predicate (sparql, "nie:mimeType"); tracker_sparql_builder_object_string (sparql, mime_type); /* FIXME: Add nie:dataSource for switching different userguides? */ tracker_sparql_builder_predicate (sparql, "tracker:available"); tracker_sparql_builder_object_boolean (sparql, TRUE); if (!is_dir) { gchar *content = NULL; gchar *title = NULL; /* Get content */ parser_get_file_content (uri, MAX_EXTRACT_SIZE, &content, &title); g_message ("Adding userguide:'%s', uri:'%s'", title, uri); if (title && title[0]) { tracker_sparql_builder_predicate (sparql, "nie:title"); tracker_sparql_builder_object_unvalidated (sparql, title); } if (content && content[0]) { tracker_sparql_builder_predicate (sparql, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (sparql, content); } g_free (content); g_free (title); } else { g_message ("Adding userguide directory:'%s'", uri); } tracker_sparql_builder_graph_close (sparql); tracker_sparql_builder_insert_close (sparql); g_free (uri); }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { FLAC__Metadata_SimpleIterator *iter; FLAC__StreamMetadata *stream = NULL, *vorbis, *picture; FLAC__bool success; FlacData fd = { 0 }; TrackerSparqlBuilder *preupdate, *metadata; gchar *filename, *uri, *artist_uri = NULL, *album_uri = NULL; const gchar *creator; GFile *file; goffset size; const gchar *graph; graph = tracker_extract_info_get_graph (info); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); if (size < 18) { g_free (filename); return FALSE; } iter = FLAC__metadata_simple_iterator_new (); success = FLAC__metadata_simple_iterator_init (iter, filename, TRUE, TRUE); g_free (filename); if (!success) { FLAC__metadata_simple_iterator_delete (iter); return FALSE; } uri = g_file_get_uri (file); do { switch (FLAC__metadata_simple_iterator_get_block_type (iter)) { case FLAC__METADATA_TYPE_STREAMINFO: stream = FLAC__metadata_simple_iterator_get_block (iter); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: vorbis = FLAC__metadata_simple_iterator_get_block (iter); parse_vorbis_comments (&(vorbis->data.vorbis_comment), &fd); FLAC__metadata_object_delete (vorbis); break; case FLAC__METADATA_TYPE_PICTURE: picture = FLAC__metadata_simple_iterator_get_block (iter); /* Deal with picture */ FLAC__metadata_object_delete (picture); break; default: break; } } while (FLAC__metadata_simple_iterator_next (iter)); creator = tracker_coalesce_strip (3, fd.artist, fd.albumartist, fd.performer); if (creator) { artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, artist_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:Artist"); tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); tracker_sparql_builder_object_unvalidated (preupdate, creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.album) { if (fd.albumartist) { album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s:%s", fd.album, fd.albumartist); } else { album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", fd.album); } tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum"); /* FIXME: nmm:albumTitle is now deprecated * tracker_sparql_builder_predicate (preupdate, "nie:title"); */ tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle"); tracker_sparql_builder_object_unvalidated (preupdate, fd.album); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); if (fd.trackcount) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_unvalidated (preupdate, fd.trackcount); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.albumgain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_double (preupdate, atof (fd.albumgain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.albumpeakgain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_double (preupdate, atof (fd.albumpeakgain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:MusicPiece"); tracker_sparql_builder_object (metadata, "nfo:Audio"); add_tuple (metadata, "nmm:performer", artist_uri); g_free (artist_uri); add_tuple (metadata, "nmm:musicAlbum", album_uri); tracker_guarantee_title_from_file (metadata, "nie:title", fd.title, uri, NULL); add_tuple (metadata, "nmm:trackNumber", fd.tracknumber); if (fd.album && album_uri) { gchar *album_disc_uri; if (fd.albumartist) { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:%s:Disc%d", fd.album, fd.albumartist, fd.discno ? atoi(fd.discno) : 1); } else { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", fd.album, fd.discno ? atoi(fd.discno) : 1); } tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc"); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_int64 (preupdate, fd.discno ? atoi (fd.discno) : 1); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_iri (preupdate, album_uri); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc"); tracker_sparql_builder_object_iri (metadata, album_disc_uri); g_free (album_disc_uri); } g_free (album_uri); /* FIXME: Trackgain/Trackpeakgain: commented out in vorbis */ add_tuple (metadata, "nie:comment", fd.comment); add_tuple (metadata, "nie:contentCreated", fd.date); add_tuple (metadata, "nfo:genre", fd.genre); add_tuple (metadata, "nie:plainTextContent", fd.lyrics); add_tuple (metadata, "nie:copyright", fd.copyright); add_tuple (metadata, "nie:license", fd.license); if (fd.publisher) { tracker_sparql_builder_predicate (metadata, "dc:publisher"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, fd.publisher); tracker_sparql_builder_object_blank_close (metadata); } if (stream) { tracker_sparql_builder_predicate (metadata, "nfo:sampleRate"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.sample_rate); tracker_sparql_builder_predicate (metadata, "nfo:channels"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.channels); tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.bits_per_sample); tracker_sparql_builder_predicate (metadata, "nfo:duration"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.total_samples / stream->data.stream_info.sample_rate); } g_free (fd.artist); g_free (fd.album); g_free (fd.albumartist); g_free (fd.performer); g_free (fd.title); g_free (fd.trackcount); g_free (fd.tracknumber); g_free (fd.discno); g_free (fd.trackgain); g_free (fd.trackpeakgain); g_free (fd.albumgain); g_free (fd.albumpeakgain); g_free (fd.date); g_free (fd.comment); g_free (fd.genre); g_free (fd.mbalbumid); g_free (fd.mbartistid); g_free (fd.mbalbumartistid); g_free (fd.mbtrackid); g_free (fd.lyrics); g_free (fd.copyright); g_free (fd.license); g_free (fd.organisation); g_free (fd.location); g_free (fd.publisher); g_free (uri); return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { struct jpeg_decompress_struct cinfo; struct tej_error_mgr tejerr; struct jpeg_marker_struct *marker; TrackerSparqlBuilder *preupdate, *metadata; TrackerXmpData *xd = NULL; TrackerExifData *ed = NULL; TrackerIptcData *id = NULL; MergeData md = { 0 }; GFile *file; FILE *f; goffset size; gchar *filename, *uri; gchar *comment = NULL; const gchar *dlna_profile, *dlna_mimetype, *graph; GPtrArray *keywords; gboolean success = TRUE; GString *where; guint i; metadata = tracker_extract_info_get_metadata_builder (info); preupdate = tracker_extract_info_get_preupdate_builder (info); graph = tracker_extract_info_get_graph (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); if (size < 18) { g_free (filename); return FALSE; } f = tracker_file_open (filename); g_free (filename); if (!f) { return FALSE; } uri = g_file_get_uri (file); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:Photo"); cinfo.err = jpeg_std_error (&tejerr.jpeg); tejerr.jpeg.error_exit = extract_jpeg_error_exit; if (setjmp (tejerr.setjmp_buffer)) { success = FALSE; goto fail; } jpeg_create_decompress (&cinfo); jpeg_save_markers (&cinfo, JPEG_COM, 0xFFFF); jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xFFFF); jpeg_save_markers (&cinfo, JPEG_APP0 + 13, 0xFFFF); jpeg_stdio_src (&cinfo, f); jpeg_read_header (&cinfo, TRUE); /* FIXME? It is possible that there are markers after SOS, * but there shouldn't be. Should we decompress the whole file? * * jpeg_start_decompress(&cinfo); * jpeg_finish_decompress(&cinfo); * * jpeg_calc_output_dimensions(&cinfo); */ marker = (struct jpeg_marker_struct *) &cinfo.marker_list; while (marker) { gchar *str; gsize len; #ifdef HAVE_LIBIPTCDATA gsize offset; guint sublen; #endif /* HAVE_LIBIPTCDATA */ switch (marker->marker) { case JPEG_COM: g_free (comment); comment = g_strndup ((gchar*) marker->data, marker->data_length); break; case JPEG_APP0 + 1: str = (gchar*) marker->data; len = marker->data_length; #ifdef HAVE_LIBEXIF if (strncmp (EXIF_NAMESPACE, str, EXIF_NAMESPACE_LENGTH) == 0) { ed = tracker_exif_new ((guchar *) marker->data, len, uri); } #endif /* HAVE_LIBEXIF */ #ifdef HAVE_EXEMPI if (strncmp (XMP_NAMESPACE, str, XMP_NAMESPACE_LENGTH) == 0) { xd = tracker_xmp_new (str + XMP_NAMESPACE_LENGTH, len - XMP_NAMESPACE_LENGTH, uri); } #endif /* HAVE_EXEMPI */ break; case JPEG_APP0 + 13: str = (gchar*) marker->data; len = marker->data_length; #ifdef HAVE_LIBIPTCDATA if (len > 0 && strncmp (PS3_NAMESPACE, str, PS3_NAMESPACE_LENGTH) == 0) { offset = iptc_jpeg_ps3_find_iptc (str, len, &sublen); if (offset > 0 && sublen > 0) { id = tracker_iptc_new (str + offset, sublen, uri); } } #endif /* HAVE_LIBIPTCDATA */ break; default: marker = marker->next; continue; } marker = marker->next; } if (!ed) { ed = g_new0 (TrackerExifData, 1); } if (!xd) { xd = g_new0 (TrackerXmpData, 1); } if (!id) { id = g_new0 (TrackerIptcData, 1); } md.title = tracker_coalesce_strip (4, xd->title, ed->document_name, xd->title2, xd->pdf_title); md.orientation = tracker_coalesce_strip (3, xd->orientation, ed->orientation, id->image_orientation); md.copyright = tracker_coalesce_strip (4, xd->copyright, xd->rights, ed->copyright, id->copyright_notice); md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); md.artist = tracker_coalesce_strip (3, xd->artist, ed->artist, xd->contributor); md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); md.date = tracker_coalesce_strip (5, xd->date, xd->time_original, ed->time, id->date_created, ed->time_original); md.description = tracker_coalesce_strip (2, xd->description, ed->description); md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); md.city = tracker_coalesce_strip (2, xd->city, id->city); md.state = tracker_coalesce_strip (2, xd->state, id->state); md.address = tracker_coalesce_strip (2, xd->address, id->sublocation); md.country = tracker_coalesce_strip (2, xd->country, id->country_name); /* FIXME We are not handling the altitude ref here for xmp */ md.gps_altitude = tracker_coalesce_strip (2, xd->gps_altitude, ed->gps_altitude); md.gps_latitude = tracker_coalesce_strip (2, xd->gps_latitude, ed->gps_latitude); md.gps_longitude = tracker_coalesce_strip (2, xd->gps_longitude, ed->gps_longitude); md.gps_direction = tracker_coalesce_strip (2, xd->gps_direction, ed->gps_direction); md.creator = tracker_coalesce_strip (3, xd->creator, id->byline, id->credit); md.comment = tracker_coalesce_strip (2, comment, ed->user_comment); md.make = tracker_coalesce_strip (2, xd->make, ed->make); md.model = tracker_coalesce_strip (2, xd->model, ed->model); /* Prioritize on native dimention in all cases */ tracker_sparql_builder_predicate (metadata, "nfo:width"); tracker_sparql_builder_object_int64 (metadata, cinfo.image_width); /* TODO: add ontology and store ed->software */ tracker_sparql_builder_predicate (metadata, "nfo:height"); tracker_sparql_builder_object_int64 (metadata, cinfo.image_height); if (guess_dlna_profile (cinfo.image_width, cinfo.image_height, &dlna_profile, &dlna_mimetype)) { tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile"); tracker_sparql_builder_object_string (metadata, dlna_profile); tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime"); tracker_sparql_builder_object_string (metadata, dlna_mimetype); } if (id->contact) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", id->contact); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, id->contact); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:representative"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } keywords = g_ptr_array_new (); if (xd->keywords) { tracker_keywords_parse (keywords, xd->keywords); } if (xd->pdf_keywords) { tracker_keywords_parse (keywords, xd->pdf_keywords); } if (xd->subject) { tracker_keywords_parse (keywords, xd->subject); } if (xd->publisher) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->publisher); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, xd->publisher); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:publisher"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (xd->type) { tracker_sparql_builder_predicate (metadata, "dc:type"); tracker_sparql_builder_object_unvalidated (metadata, xd->type); } if (xd->rating) { tracker_sparql_builder_predicate (metadata, "nao:numericRating"); tracker_sparql_builder_object_unvalidated (metadata, xd->rating); } if (xd->format) { tracker_sparql_builder_predicate (metadata, "dc:format"); tracker_sparql_builder_object_unvalidated (metadata, xd->format); } if (xd->identifier) { tracker_sparql_builder_predicate (metadata, "dc:identifier"); tracker_sparql_builder_object_unvalidated (metadata, xd->identifier); } if (xd->source) { tracker_sparql_builder_predicate (metadata, "dc:source"); tracker_sparql_builder_object_unvalidated (metadata, xd->source); } if (xd->language) { tracker_sparql_builder_predicate (metadata, "dc:language"); tracker_sparql_builder_object_unvalidated (metadata, xd->language); } if (xd->relation) { tracker_sparql_builder_predicate (metadata, "dc:relation"); tracker_sparql_builder_object_unvalidated (metadata, xd->relation); } if (xd->coverage) { tracker_sparql_builder_predicate (metadata, "dc:coverage"); tracker_sparql_builder_object_unvalidated (metadata, xd->coverage); } if (xd->license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, xd->license); } if (xd->regions) { tracker_xmp_apply_regions (preupdate, metadata, graph, xd); } if (id->keywords) { tracker_keywords_parse (keywords, id->keywords); } where = g_string_new (""); for (i = 0; i < keywords->len; i++) { gchar *p, *escaped, *var; p = g_ptr_array_index (keywords, i); escaped = tracker_sparql_escape_string (p); var = g_strdup_printf ("tag%d", i + 1); /* ensure tag with specified label exists */ tracker_sparql_builder_append (preupdate, "INSERT { "); if (graph) { tracker_sparql_builder_append (preupdate, "GRAPH <"); tracker_sparql_builder_append (preupdate, graph); tracker_sparql_builder_append (preupdate, "> { "); } tracker_sparql_builder_append (preupdate, "_:tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\""); if (graph) { tracker_sparql_builder_append (preupdate, " } "); } tracker_sparql_builder_append (preupdate, " }\n"); tracker_sparql_builder_append (preupdate, "WHERE { FILTER (NOT EXISTS { " "?tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\" }) }\n"); /* associate file with tag */ tracker_sparql_builder_predicate (metadata, "nao:hasTag"); tracker_sparql_builder_object_variable (metadata, var); g_string_append_printf (where, "?%s a nao:Tag ; nao:prefLabel \"%s\" .\n", var, escaped); g_free (var); g_free (escaped); g_free (p); } g_ptr_array_free (keywords, TRUE); tracker_extract_info_set_where_clause (info, where->str); g_string_free (where, TRUE); if (md.make || md.model) { gchar *equip_uri; equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", md.make ? md.make : "", md.model ? md.model : ""); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, equip_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nfo:Equipment"); if (md.make) { tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer"); tracker_sparql_builder_object_unvalidated (preupdate, md.make); } if (md.model) { tracker_sparql_builder_predicate (preupdate, "nfo:model"); tracker_sparql_builder_object_unvalidated (preupdate, md.model); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nfo:equipment"); tracker_sparql_builder_object_iri (metadata, equip_uri); g_free (equip_uri); } tracker_guarantee_title_from_file (metadata, "nie:title", md.title, uri, NULL); if (md.orientation) { tracker_sparql_builder_predicate (metadata, "nfo:orientation"); tracker_sparql_builder_object (metadata, md.orientation); } if (md.copyright) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, md.copyright); } if (md.white_balance) { tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance"); tracker_sparql_builder_object (metadata, md.white_balance); } if (md.fnumber) { gdouble value; value = g_strtod (md.fnumber, NULL); tracker_sparql_builder_predicate (metadata, "nmm:fnumber"); tracker_sparql_builder_object_double (metadata, value); } if (md.flash) { tracker_sparql_builder_predicate (metadata, "nmm:flash"); tracker_sparql_builder_object (metadata, md.flash); } if (md.focal_length) { gdouble value; value = g_strtod (md.focal_length, NULL); tracker_sparql_builder_predicate (metadata, "nmm:focalLength"); tracker_sparql_builder_object_double (metadata, value); } if (md.artist) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.artist); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.artist); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:contributor"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (md.exposure_time) { gdouble value; value = g_strtod (md.exposure_time, NULL); tracker_sparql_builder_predicate (metadata, "nmm:exposureTime"); tracker_sparql_builder_object_double (metadata, value); } if (md.iso_speed_ratings) { gdouble value; value = g_strtod (md.iso_speed_ratings, NULL); tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed"); tracker_sparql_builder_object_double (metadata, value); } tracker_guarantee_date_from_file_mtime (metadata, "nie:contentCreated", md.date, uri); if (md.description) { tracker_sparql_builder_predicate (metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (metadata, md.description); } if (md.metering_mode) { tracker_sparql_builder_predicate (metadata, "nmm:meteringMode"); tracker_sparql_builder_object (metadata, md.metering_mode); } if (md.creator) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); /* NOTE: We only have affiliation with * nco:PersonContact and we are using * nco:Contact here. */ /* if (id->byline_title) { */ /* tracker_sparql_builder_insert_open (preupdate, NULL); */ /* tracker_sparql_builder_subject (preupdate, "_:affiliation_by_line"); */ /* tracker_sparql_builder_predicate (preupdate, "a"); */ /* tracker_sparql_builder_object (preupdate, "nco:Affiliation"); */ /* tracker_sparql_builder_predicate (preupdate, "nco:title"); */ /* tracker_sparql_builder_object_unvalidated (preupdate, id->byline_title); */ /* tracker_sparql_builder_insert_close (preupdate); */ /* tracker_sparql_builder_predicate (preupdate, "a"); */ /* tracker_sparql_builder_object (preupdate, "nco:Contact"); */ /* tracker_sparql_builder_predicate (preupdate, "nco:hasAffiliation"); */ /* tracker_sparql_builder_object (preupdate, "_:affiliation_by_line"); */ /* } */ tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (md.comment) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, md.comment); } if (md.address || md.state || md.country || md.city || md.gps_altitude || md.gps_latitude || md.gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:location"); tracker_sparql_builder_object_blank_open (metadata); /* GeoPoint */ tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "slo:GeoLocation"); if (md.address || md.state || md.country || md.city) { gchar *addruri; addruri = tracker_sparql_get_uuid_urn (); tracker_sparql_builder_predicate (metadata, "slo:postalAddress"); tracker_sparql_builder_object_iri (metadata, addruri); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, addruri); g_free (addruri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:PostalAddress"); if (md.address) { tracker_sparql_builder_predicate (preupdate, "nco:streetAddress"); tracker_sparql_builder_object_unvalidated (preupdate, md.address); } if (md.state) { tracker_sparql_builder_predicate (preupdate, "nco:region"); tracker_sparql_builder_object_unvalidated (preupdate, md.state); } if (md.city) { tracker_sparql_builder_predicate (preupdate, "nco:locality"); tracker_sparql_builder_object_unvalidated (preupdate, md.city); } if (md.country) { tracker_sparql_builder_predicate (preupdate, "nco:country"); tracker_sparql_builder_object_unvalidated (preupdate, md.country); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (md.gps_altitude) { tracker_sparql_builder_predicate (metadata, "slo:altitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_altitude); } if (md.gps_latitude) { tracker_sparql_builder_predicate (metadata, "slo:latitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_latitude); } if (md.gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:longitude"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_longitude); } tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */ } if (md.gps_direction) { tracker_sparql_builder_predicate (metadata, "nfo:heading"); tracker_sparql_builder_object_unvalidated (metadata, md.gps_direction); } if (cinfo.density_unit != 0 || ed->x_resolution) { gdouble value; if (cinfo.density_unit == 0) { if (ed->resolution_unit != 3) value = g_strtod (ed->x_resolution, NULL); else value = g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; } else { if (cinfo.density_unit == 1) value = cinfo.X_density; else value = cinfo.X_density * CM_TO_INCH; } tracker_sparql_builder_predicate (metadata, "nfo:horizontalResolution"); tracker_sparql_builder_object_double (metadata, value); } if (cinfo.density_unit != 0 || ed->y_resolution) { gdouble value; if (cinfo.density_unit == 0) { if (ed->resolution_unit != 3) value = g_strtod (ed->y_resolution, NULL); else value = g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; } else { if (cinfo.density_unit == 1) value = cinfo.Y_density; else value = cinfo.Y_density * CM_TO_INCH; } tracker_sparql_builder_predicate (metadata, "nfo:verticalResolution"); tracker_sparql_builder_object_double (metadata, value); } jpeg_destroy_decompress (&cinfo); tracker_exif_free (ed); tracker_xmp_free (xd); tracker_iptc_free (id); g_free (comment); fail: tracker_file_close (f, FALSE); g_free (uri); return success; }
static void extract_ps_from_filestream (FILE *f, TrackerSparqlBuilder *preupdate, TrackerSparqlBuilder *metadata) { gchar *line; gsize length; gssize read_char; gsize accum; gsize max_bytes; line = NULL; length = 0; tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:PaginatedTextDocument"); /* 20 MiB should be enough! (original safe limit) */ accum = 0; max_bytes = 20u << 20; /* Reuse the same buffer for all lines. Must be dynamically allocated with * malloc family methods as getline() may re-size it with realloc() */ length = 1024; line = g_malloc (length); /* Halt the whole when one of these conditions is met: * a) Reached max bytes to read * b) No more lines to read */ while ((accum < max_bytes) && (read_char = tracker_getline (&line, &length, f)) != -1) { gboolean pageno_atend = FALSE; gboolean header_finished = FALSE; /* Update accumulated bytes read */ accum += read_char; line[read_char - 1] = '\0'; /* overwrite '\n' char */ if (!header_finished && strncmp (line, "%%Copyright:", 12) == 0) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, line + 13); } else if (!header_finished && strncmp (line, "%%Title:", 8) == 0) { tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (metadata, line + 9); } else if (!header_finished && strncmp (line, "%%Creator:", 10) == 0) { tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, line + 11); tracker_sparql_builder_object_blank_close (metadata); } else if (!header_finished && strncmp (line, "%%CreationDate:", 15) == 0) { gchar *date; date = date_to_iso8601 (line + 16); if (date) { tracker_sparql_builder_predicate (metadata, "nie:contentCreated"); tracker_sparql_builder_object_unvalidated (metadata, date); g_free (date); } } else if (strncmp (line, "%%Pages:", 8) == 0) { if (strcmp (line + 9, "(atend)") == 0) { pageno_atend = TRUE; } else { gint64 page_count; page_count = g_ascii_strtoll (line + 9, NULL, 10); tracker_sparql_builder_predicate (metadata, "nfo:pageCount"); tracker_sparql_builder_object_int64 (metadata, page_count); } } else if (strncmp (line, "%%EndComments", 14) == 0) { header_finished = TRUE; if (!pageno_atend) { break; } } } /* Deallocate the buffer */ if (line) { g_free (line); } }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerConfig *config; GTime creation_date; GError *error = NULL; TrackerSparqlBuilder *metadata, *preupdate; const gchar *graph; const gchar *urn; TrackerXmpData *xd = NULL; PDFData pd = { 0 }; /* actual data */ PDFData md = { 0 }; /* for merging */ PopplerDocument *document; gchar *xml = NULL; gchar *content, *uri; guint n_bytes; GPtrArray *keywords; guint i; GFile *file; gchar *filename; int fd; gchar *contents = NULL; gsize len; struct stat st; metadata = tracker_extract_info_get_metadata_builder (info); preupdate = tracker_extract_info_get_preupdate_builder (info); graph = tracker_extract_info_get_graph (info); urn = tracker_extract_info_get_urn (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); fd = tracker_file_open_fd (filename); if (fd == -1) { g_warning ("Could not open pdf file '%s': %s\n", filename, g_strerror (errno)); g_free (filename); return FALSE; } if (fstat (fd, &st) == -1) { g_warning ("Could not fstat pdf file '%s': %s\n", filename, g_strerror (errno)); close (fd); g_free (filename); return FALSE; } if (st.st_size == 0) { contents = NULL; len = 0; } else { contents = (gchar *) mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (contents == NULL || contents == MAP_FAILED) { g_warning ("Could not mmap pdf file '%s': %s\n", filename, g_strerror (errno)); close (fd); g_free (filename); return FALSE; } len = st.st_size; } g_free (filename); uri = g_file_get_uri (file); document = poppler_document_new_from_data (contents, len, NULL, &error); if (error) { if (error->code == POPPLER_ERROR_ENCRYPTED) { tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:PaginatedTextDocument"); tracker_sparql_builder_predicate (metadata, "nfo:isContentEncrypted"); tracker_sparql_builder_object_boolean (metadata, TRUE); g_error_free (error); g_free (uri); close (fd); return TRUE; } else { g_warning ("Couldn't create PopplerDocument from uri:'%s', %s", uri, error->message ? error->message : "no error given"); g_error_free (error); g_free (uri); close (fd); return FALSE; } } if (!document) { g_warning ("Could not create PopplerDocument from uri:'%s', " "NULL returned without an error", uri); g_free (uri); close (fd); return FALSE; } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:PaginatedTextDocument"); g_object_get (document, "title", &pd.title, "author", &pd.author, "subject", &pd.subject, "keywords", &pd.keywords, "creation-date", &creation_date, "metadata", &xml, NULL); if (creation_date > 0) { pd.creation_date = tracker_date_to_string ((time_t) creation_date); } keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); if (xml && *xml && (xd = tracker_xmp_new (xml, strlen (xml), uri)) != NULL) { /* The casts here are well understood and known */ md.title = (gchar *) tracker_coalesce_strip (4, pd.title, xd->title, xd->title2, xd->pdf_title); md.subject = (gchar *) tracker_coalesce_strip (2, pd.subject, xd->subject); md.date = (gchar *) tracker_coalesce_strip (3, pd.creation_date, xd->date, xd->time_original); md.author = (gchar *) tracker_coalesce_strip (2, pd.author, xd->creator); write_pdf_data (md, metadata, keywords); if (xd->keywords) { tracker_keywords_parse (keywords, xd->keywords); } if (xd->pdf_keywords) { tracker_keywords_parse (keywords, xd->pdf_keywords); } if (xd->publisher) { tracker_sparql_builder_predicate (metadata, "nco:publisher"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, xd->publisher); tracker_sparql_builder_object_blank_close (metadata); } if (xd->type) { tracker_sparql_builder_predicate (metadata, "dc:type"); tracker_sparql_builder_object_unvalidated (metadata, xd->type); } if (xd->format) { tracker_sparql_builder_predicate (metadata, "dc:format"); tracker_sparql_builder_object_unvalidated (metadata, xd->format); } if (xd->identifier) { tracker_sparql_builder_predicate (metadata, "dc:identifier"); tracker_sparql_builder_object_unvalidated (metadata, xd->identifier); } if (xd->source) { tracker_sparql_builder_predicate (metadata, "dc:source"); tracker_sparql_builder_object_unvalidated (metadata, xd->source); } if (xd->language) { tracker_sparql_builder_predicate (metadata, "dc:language"); tracker_sparql_builder_object_unvalidated (metadata, xd->language); } if (xd->relation) { tracker_sparql_builder_predicate (metadata, "dc:relation"); tracker_sparql_builder_object_unvalidated (metadata, xd->relation); } if (xd->coverage) { tracker_sparql_builder_predicate (metadata, "dc:coverage"); tracker_sparql_builder_object_unvalidated (metadata, xd->coverage); } if (xd->license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, xd->license); } if (xd->make || xd->model) { gchar *equip_uri; equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", xd->make ? xd->make : "", xd->model ? xd->model : ""); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, equip_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nfo:Equipment"); if (xd->make) { tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer"); tracker_sparql_builder_object_unvalidated (preupdate, xd->make); } if (xd->model) { tracker_sparql_builder_predicate (preupdate, "nfo:model"); tracker_sparql_builder_object_unvalidated (preupdate, xd->model); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nfo:equipment"); tracker_sparql_builder_object_iri (metadata, equip_uri); g_free (equip_uri); } if (xd->orientation) { tracker_sparql_builder_predicate (metadata, "nfo:orientation"); tracker_sparql_builder_object (metadata, xd->orientation); } if (xd->rights) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, xd->rights); } if (xd->white_balance) { tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance"); tracker_sparql_builder_object (metadata, xd->white_balance); } if (xd->fnumber) { gdouble value; value = g_strtod (xd->fnumber, NULL); tracker_sparql_builder_predicate (metadata, "nmm:fnumber"); tracker_sparql_builder_object_double (metadata, value); } if (xd->flash) { tracker_sparql_builder_predicate (metadata, "nmm:flash"); tracker_sparql_builder_object (metadata, xd->flash); } if (xd->focal_length) { gdouble value; value = g_strtod (xd->focal_length, NULL); tracker_sparql_builder_predicate (metadata, "nmm:focalLength"); tracker_sparql_builder_object_double (metadata, value); } /* Question: Shouldn't xd->Artist be merged with md.author instead? */ if (xd->artist || xd->contributor) { const gchar *artist; artist = tracker_coalesce_strip (2, xd->artist, xd->contributor); tracker_sparql_builder_predicate (metadata, "nco:contributor"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, artist); tracker_sparql_builder_object_blank_close (metadata); } if (xd->exposure_time) { gdouble value; value = g_strtod (xd->exposure_time, NULL); tracker_sparql_builder_predicate (metadata, "nmm:exposureTime"); tracker_sparql_builder_object_double (metadata, value); } if (xd->iso_speed_ratings) { gdouble value; value = g_strtod (xd->iso_speed_ratings, NULL); tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed"); tracker_sparql_builder_object_double (metadata, value); } if (xd->description) { tracker_sparql_builder_predicate (metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (metadata, xd->description); } if (xd->metering_mode) { tracker_sparql_builder_predicate (metadata, "nmm:meteringMode"); tracker_sparql_builder_object (metadata, xd->metering_mode); } if (xd->address || xd->state || xd->country || xd->city || xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:location"); tracker_sparql_builder_object_blank_open (metadata); /* GeoLocation */ tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "slo:GeoLocation"); if (xd->address || xd->state || xd->country || xd->city) { gchar *addruri; addruri = tracker_sparql_get_uuid_urn (); tracker_sparql_builder_predicate (metadata, "slo:postalAddress"); tracker_sparql_builder_object_iri (metadata, addruri); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, addruri); g_free (addruri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:PostalAddress"); if (xd->address) { tracker_sparql_builder_predicate (preupdate, "nco:streetAddress"); tracker_sparql_builder_object_unvalidated (preupdate, xd->address); } if (xd->state) { tracker_sparql_builder_predicate (preupdate, "nco:region"); tracker_sparql_builder_object_unvalidated (preupdate, xd->state); } if (xd->city) { tracker_sparql_builder_predicate (preupdate, "nco:locality"); tracker_sparql_builder_object_unvalidated (preupdate, xd->city); } if (xd->country) { tracker_sparql_builder_predicate (preupdate, "nco:country"); tracker_sparql_builder_object_unvalidated (preupdate, xd->country); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (xd->gps_altitude) { tracker_sparql_builder_predicate (metadata, "slo:altitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_altitude); } if (xd->gps_latitude) { tracker_sparql_builder_predicate (metadata, "slo:latitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_latitude); } if (xd->gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:longitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_longitude); } tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */ } if (xd->regions) { tracker_xmp_apply_regions (preupdate, metadata, graph, xd); } tracker_xmp_free (xd); } else { /* So if we are here we have NO XMP data and we just * write what we know from Poppler. */ write_pdf_data (pd, metadata, keywords); } for (i = 0; i < keywords->len; i++) { gchar *escaped, *subject; const gchar *p; p = g_ptr_array_index (keywords, i); escaped = tracker_sparql_escape_string (p); subject = g_strdup_printf ("_:tag%d", i + 1); /* ensure tag with specified label exists */ tracker_sparql_builder_insert_open (preupdate, graph); tracker_sparql_builder_subject (preupdate, subject); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nao:Tag"); tracker_sparql_builder_predicate (preupdate, "nao:prefLabel"); tracker_sparql_builder_object_unvalidated (preupdate, escaped); tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_append (preupdate, "WHERE { FILTER (NOT EXISTS { " "?tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\" }) }\n"); /* associate file with tag */ tracker_sparql_builder_insert_open (preupdate, graph); tracker_sparql_builder_subject_iri (preupdate, urn); tracker_sparql_builder_predicate (preupdate, "nao:hasTag"); tracker_sparql_builder_object (preupdate, "?tag"); tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject (preupdate, "?tag"); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nao:Tag"); tracker_sparql_builder_predicate (preupdate, "nao:prefLabel"); tracker_sparql_builder_object_unvalidated (preupdate, escaped); tracker_sparql_builder_where_close (preupdate); g_free (subject); g_free (escaped); } g_ptr_array_free (keywords, TRUE); tracker_sparql_builder_predicate (metadata, "nfo:pageCount"); tracker_sparql_builder_object_int64 (metadata, poppler_document_get_n_pages (document)); config = tracker_main_get_config (); n_bytes = tracker_config_get_max_bytes (config); content = extract_content_text (document, n_bytes); if (content) { tracker_sparql_builder_predicate (metadata, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (metadata, content); g_free (content); } read_outline (document, metadata); g_free (xml); g_free (pd.keywords); g_free (pd.title); g_free (pd.subject); g_free (pd.creation_date); g_free (pd.author); g_free (pd.date); g_free (uri); g_object_unref (document); if (contents) { munmap (contents, len); } close (fd); return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *preupdate, *metadata; goffset size; GifFileType *gifFile = NULL; GString *where; const gchar *graph; gchar *filename, *uri; GFile *file; int fd; #if GIFLIB_MAJOR >= 5 int err; #endif preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); if (size < 64) { g_free (filename); return FALSE; } fd = tracker_file_open_fd (filename); if (fd == -1) { g_warning ("Could not open GIF file '%s': %s\n", filename, g_strerror (errno)); g_free (filename); return FALSE; } #if GIFLIB_MAJOR < 5 if ((gifFile = DGifOpenFileHandle (fd)) == NULL) { PrintGifError (); #else /* GIFLIB_MAJOR < 5 */ if ((gifFile = DGifOpenFileHandle (fd, &err)) == NULL) { gif_error ("Could not open GIF file with handle", err); #endif /* GIFLIB_MAJOR < 5 */ close (fd); return FALSE; } g_free (filename); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_object (metadata, "nmm:Photo"); where = g_string_new (""); uri = g_file_get_uri (file); read_metadata (preupdate, metadata, where, gifFile, uri, graph); tracker_extract_info_set_where_clause (info, where->str); g_string_free (where, TRUE); g_free (uri); if (DGifCloseFile (gifFile) != GIF_OK) { #if GIFLIB_MAJOR < 5 PrintGifError (); #else /* GIFLIB_MAJOR < 5 */ gif_error ("Could not close GIF file", gifFile->Error); #endif /* GIFLIB_MAJOR < 5 */ } return TRUE; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { TrackerSparqlBuilder *metadata; GFile *file; TrackerConfig *config; htmlDocPtr doc; parser_data pd; gchar *filename; xmlSAXHandler handler = { NULL, /* internalSubset */ NULL, /* isStandalone */ NULL, /* hasInternalSubset */ NULL, /* hasExternalSubset */ NULL, /* resolveEntity */ NULL, /* getEntity */ NULL, /* entityDecl */ NULL, /* notationDecl */ NULL, /* attributeDecl */ NULL, /* elementDecl */ NULL, /* unparsedEntityDecl */ NULL, /* setDocumentLocator */ NULL, /* startDocument */ NULL, /* endDocument */ parser_start_element, /* startElement */ parser_end_element, /* endElement */ NULL, /* reference */ parser_characters, /* characters */ NULL, /* ignorableWhitespace */ NULL, /* processingInstruction */ NULL, /* comment */ NULL, /* xmlParserWarning */ NULL, /* xmlParserError */ NULL, /* xmlParserError */ NULL, /* getParameterEntity */ NULL, /* cdataBlock */ NULL, /* externalSubset */ 1, /* initialized */ NULL, /* private */ NULL, /* startElementNsSAX2Func */ NULL, /* endElementNsSAX2Func */ NULL /* xmlStructuredErrorFunc */ }; metadata = tracker_extract_info_get_metadata_builder (info); file = tracker_extract_info_get_file (info); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:HtmlDocument"); pd.metadata = metadata; pd.current = -1; pd.in_body = FALSE; pd.plain_text = g_string_new (NULL); pd.title = g_string_new (NULL); config = tracker_main_get_config (); pd.n_bytes_remaining = tracker_config_get_max_bytes (config); filename = g_file_get_path (file); doc = htmlSAXParseFile (filename, NULL, &handler, &pd); g_free (filename); if (doc) { xmlFreeDoc (doc); } g_strstrip (pd.plain_text->str); g_strstrip (pd.title->str); if (pd.title->str && *pd.title->str != '\0') { tracker_sparql_builder_predicate (metadata, "nie:title"); tracker_sparql_builder_object_unvalidated (metadata, pd.title->str); } if (pd.plain_text->str && *pd.plain_text->str != '\0') { tracker_sparql_builder_predicate (metadata, "nie:plainTextContent"); tracker_sparql_builder_object_unvalidated (metadata, pd.plain_text->str); } g_string_free (pd.plain_text, TRUE); g_string_free (pd.title, TRUE); return TRUE; }
/* If a reset is requested, we will remove from the store all items previously * inserted by the tracker-miner-applications, this is: * (a) all elements which are nfo:softwareIcon of a given nfo:Software * (b) all nfo:Software in our graph (includes both applications and maemo applets) * (c) all elements which are nfo:softwareCategoryIcon of a given nfo:SoftwareCategory * (d) all nfo:SoftwareCategory in our graph */ static void miner_applications_reset (TrackerMiner *miner) { GError *error = NULL; TrackerSparqlBuilder *sparql; sparql = tracker_sparql_builder_new_update (); /* (a) all elements which are nfo:softwareIcon of a given nfo:Software */ tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_variable (sparql, "icon"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_delete_close (sparql); tracker_sparql_builder_where_open (sparql); tracker_sparql_builder_subject_variable (sparql, "software"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:Software"); tracker_sparql_builder_subject_variable (sparql, "icon"); tracker_sparql_builder_predicate (sparql, "nfo:softwareIcon"); tracker_sparql_builder_object_variable (sparql, "software"); tracker_sparql_builder_where_close (sparql); /* (b) all nfo:Software in our graph (includes both applications and maemo applets) */ tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_variable (sparql, "software"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_delete_close (sparql); tracker_sparql_builder_where_open (sparql); tracker_sparql_builder_subject_variable (sparql, "software"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:Software"); tracker_sparql_builder_where_close (sparql); /* (c) all elements which are nfo:softwareCategoryIcon of a given nfo:SoftwareCategory */ tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_variable (sparql, "icon"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_delete_close (sparql); tracker_sparql_builder_where_open (sparql); tracker_sparql_builder_subject_variable (sparql, "category"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); tracker_sparql_builder_subject_variable (sparql, "icon"); tracker_sparql_builder_predicate (sparql, "nfo:softwareCategoryIcon"); tracker_sparql_builder_object_variable (sparql, "category"); tracker_sparql_builder_where_close (sparql); /* (d) all nfo:SoftwareCategory in our graph */ tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); tracker_sparql_builder_subject_variable (sparql, "category"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "rdfs:Resource"); tracker_sparql_builder_delete_close (sparql); tracker_sparql_builder_where_open (sparql); tracker_sparql_builder_subject_variable (sparql, "category"); tracker_sparql_builder_predicate (sparql, "a"); tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); tracker_sparql_builder_where_close (sparql); /* Execute a sync update, we don't want the apps miner to start before * we finish this. */ tracker_sparql_connection_update (tracker_miner_get_connection (miner), tracker_sparql_builder_get_result (sparql), G_PRIORITY_HIGH, NULL, &error); if (error) { /* Some error happened performing the query, not good */ g_critical ("Couldn't reset mined applications: %s", error ? error->message : "unknown error"); g_error_free (error); } g_object_unref (sparql); }
static void parser_start_element (void *data, const xmlChar *name_, const xmlChar **attrs_) { parser_data *pd = data; const gchar *name = (const gchar*) name_; const gchar **attrs = (const gchar**) attrs_; if (!pd || !name) { return; } /* Look for RDFa triple describing the license */ if (g_ascii_strcasecmp (name, "a") == 0) { /* This tag is a license. Ignore, however, if it is * referring to another document. */ if (has_attribute (attrs, "rel", "license") && has_attribute (attrs, "about", NULL) == FALSE) { const xmlChar *href; href = lookup_attribute (attrs, "href"); if (href) { tracker_sparql_builder_predicate (pd->metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (pd->metadata, href); } } } else if (g_ascii_strcasecmp (name, "title") == 0) { pd->current = READ_TITLE; } else if (g_ascii_strcasecmp (name, "meta") == 0) { if (has_attribute (attrs, "name", "author")) { const xmlChar *author; author = lookup_attribute (attrs, "content"); if (author) { tracker_sparql_builder_predicate (pd->metadata, "nco:creator"); tracker_sparql_builder_object_blank_open (pd->metadata); tracker_sparql_builder_predicate (pd->metadata, "a"); tracker_sparql_builder_object (pd->metadata, "nco:Contact"); tracker_sparql_builder_predicate (pd->metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (pd->metadata, author); tracker_sparql_builder_object_blank_close (pd->metadata); } } if (has_attribute (attrs, "name", "description")) { const xmlChar *desc; desc = lookup_attribute (attrs,"content"); if (desc) { tracker_sparql_builder_predicate (pd->metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (pd->metadata, desc); } } if (has_attribute (attrs, "name", "keywords")) { const xmlChar* content = lookup_attribute (attrs, "content"); if (content) { gchar **keywords; gint i; keywords = g_strsplit (content, ",", -1); if (keywords) { for (i = 0; keywords[i] != NULL; i++) { if (!keywords[i] || keywords[i] == '\0') { continue; } tracker_sparql_builder_predicate (pd->metadata, "nie:keyword"); tracker_sparql_builder_object_unvalidated (pd->metadata, g_strstrip (keywords[i])); } g_strfreev (keywords); } } } } else if (g_ascii_strcasecmp (name, "body") == 0) { pd->in_body = TRUE; } else if (g_ascii_strcasecmp (name, "script") == 0) { /* Ignore javascript and such */ pd->current = READ_IGNORE; } }
static void read_metadata (TrackerSparqlBuilder *preupdate, TrackerSparqlBuilder *metadata, GString *where, GifFileType *gifFile, const gchar *uri, const gchar *graph) { GifRecordType RecordType; int frameheight; int framewidth; unsigned char *framedata = NULL; GPtrArray *keywords; guint i; int status; MergeData md = { 0 }; GifData gd = { 0 }; TrackerXmpData *xd = NULL; do { GifByteType *ExtData; int ExtCode; ExtBlock extBlock; if (DGifGetRecordType(gifFile, &RecordType) == GIF_ERROR) { #if GIFLIB_MAJOR < 5 PrintGifError (); #else /* GIFLIB_MAJOR < 5 */ gif_error ("Could not read next GIF record type", gifFile->Error); #endif /* GIFLIB_MAJOR < 5 */ return; } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(gifFile) == GIF_ERROR) { #if GIFLIB_MAJOR < 5 PrintGifError(); #else /* GIFLIB_MAJOR < 5 */ gif_error ("Could not get GIF record information", gifFile->Error); #endif /* GIFLIB_MAJOR < 5 */ return; } framewidth = gifFile->Image.Width; frameheight = gifFile->Image.Height; framedata = g_malloc (framewidth*frameheight); if (DGifGetLine(gifFile, framedata, framewidth*frameheight)==GIF_ERROR) { #if GIFLIB_MAJOR < 5 PrintGifError(); #else /* GIFLIB_MAJOR < 5 */ gif_error ("Could not load a block of GIF pixes", gifFile->Error); #endif /* GIFLIB_MAJOR < 5 */ return; } gd.width = g_strdup_printf ("%d", framewidth); gd.height = g_strdup_printf ("%d", frameheight); g_free (framedata); break; case EXTENSION_RECORD_TYPE: extBlock.bytes = NULL; extBlock.byteCount = 0; if ((status = DGifGetExtension (gifFile, &ExtCode, &ExtData)) != GIF_OK) { g_warning ("Problem getting the extension"); return; } #if defined(HAVE_EXEMPI) if (ExtData && *ExtData && strncmp (&ExtData[1],"XMP Data",8) == 0) { while (ExtData != NULL && status == GIF_OK ) { if ((status = DGifGetExtensionNext (gifFile, &ExtData)) == GIF_OK) { if (ExtData != NULL) { if (ext_block_append (&extBlock, ExtData[0]+1, (char *) &(ExtData[0])) != GIF_OK) { g_warning ("Problem with extension data"); return; } } } } xd = tracker_xmp_new (extBlock.bytes, extBlock.byteCount-XMP_MAGIC_TRAILER_LENGTH, uri); g_free (extBlock.bytes); } else #endif /* See Section 24. Comment Extension. in the GIF format definition */ if (ExtCode == EXTENSION_RECORD_COMMENT_BLOCK_CODE && ExtData && *ExtData) { guint block_count = 0; /* Merge all blocks */ do { block_count++; g_debug ("Comment Extension block found (#%u, %u bytes)", block_count, ExtData[0]); if (ext_block_append (&extBlock, ExtData[0], (char *) &(ExtData[1])) != GIF_OK) { g_warning ("Problem with Comment extension data"); return; } } while (((status = DGifGetExtensionNext(gifFile, &ExtData)) == GIF_OK) && ExtData != NULL); /* Add last NUL byte */ g_debug ("Comment Extension blocks found (%u) with %u bytes", block_count, extBlock.byteCount); extBlock.bytes = g_realloc (extBlock.bytes, extBlock.byteCount + 1); extBlock.bytes[extBlock.byteCount] = '\0'; /* Set commentt */ gd.comment = extBlock.bytes; } else { do { status = DGifGetExtensionNext(gifFile, &ExtData); } while ( status == GIF_OK && ExtData != NULL); } break; case TERMINATE_RECORD_TYPE: break; default: break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (!xd) { xd = g_new0 (TrackerXmpData, 1); } md.title = tracker_coalesce_strip (3, xd->title, xd->title2, xd->pdf_title); md.date = tracker_coalesce_strip (2, xd->date, xd->time_original); md.artist = tracker_coalesce_strip (2, xd->artist, xd->contributor); if (xd->license) { tracker_sparql_builder_predicate (metadata, "nie:license"); tracker_sparql_builder_object_unvalidated (metadata, xd->license); } if (xd->creator) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, xd->creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } tracker_guarantee_date_from_file_mtime (metadata, "nie:contentCreated", md.date, uri); if (xd->description) { tracker_sparql_builder_predicate (metadata, "nie:description"); tracker_sparql_builder_object_unvalidated (metadata, xd->description); } if (xd->copyright) { tracker_sparql_builder_predicate (metadata, "nie:copyright"); tracker_sparql_builder_object_unvalidated (metadata, xd->copyright); } if (xd->make || xd->model) { gchar *equip_uri; equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", xd->make ? xd->make : "", xd->model ? xd->model : ""); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, equip_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nfo:Equipment"); if (xd->make) { tracker_sparql_builder_predicate (preupdate, "nfo:manufacturer"); tracker_sparql_builder_object_unvalidated (preupdate, xd->make); } if (xd->model) { tracker_sparql_builder_predicate (preupdate, "nfo:model"); tracker_sparql_builder_object_unvalidated (preupdate, xd->model); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nfo:equipment"); tracker_sparql_builder_object_iri (metadata, equip_uri); g_free (equip_uri); } tracker_guarantee_title_from_file (metadata, "nie:title", md.title, uri, NULL); if (md.artist) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", md.artist); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, md.artist); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:contributor"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (xd->orientation) { tracker_sparql_builder_predicate (metadata, "nfo:orientation"); tracker_sparql_builder_object_unvalidated (metadata, xd->orientation); } if (xd->exposure_time) { tracker_sparql_builder_predicate (metadata, "nmm:exposureTime"); tracker_sparql_builder_object_unvalidated (metadata, xd->exposure_time); } if (xd->iso_speed_ratings) { tracker_sparql_builder_predicate (metadata, "nmm:isoSpeed"); tracker_sparql_builder_object_unvalidated (metadata, xd->iso_speed_ratings); } if (xd->white_balance) { tracker_sparql_builder_predicate (metadata, "nmm:whiteBalance"); tracker_sparql_builder_object_unvalidated (metadata, xd->white_balance); } if (xd->fnumber) { tracker_sparql_builder_predicate (metadata, "nmm:fnumber"); tracker_sparql_builder_object_unvalidated (metadata, xd->fnumber); } if (xd->flash) { tracker_sparql_builder_predicate (metadata, "nmm:flash"); tracker_sparql_builder_object_unvalidated (metadata, xd->flash); } if (xd->focal_length) { tracker_sparql_builder_predicate (metadata, "nmm:focalLength"); tracker_sparql_builder_object_unvalidated (metadata, xd->focal_length); } if (xd->metering_mode) { tracker_sparql_builder_predicate (metadata, "nmm:meteringMode"); tracker_sparql_builder_object_unvalidated (metadata, xd->metering_mode); } keywords = g_ptr_array_new (); if (xd->keywords) { tracker_keywords_parse (keywords, xd->keywords); } if (xd->pdf_keywords) { tracker_keywords_parse (keywords, xd->pdf_keywords); } if (xd->rating) { tracker_sparql_builder_predicate (metadata, "nao:numericRating"); tracker_sparql_builder_object_unvalidated (metadata, xd->rating); } if (xd->subject) { tracker_keywords_parse (keywords, xd->subject); } if (xd->regions) { tracker_xmp_apply_regions (preupdate, metadata, graph, xd); } for (i = 0; i < keywords->len; i++) { gchar *p, *escaped, *var; p = g_ptr_array_index (keywords, i); escaped = tracker_sparql_escape_string (p); var = g_strdup_printf ("tag%d", i + 1); /* ensure tag with specified label exists */ tracker_sparql_builder_append (preupdate, "INSERT { "); if (graph) { tracker_sparql_builder_append (preupdate, "GRAPH <"); tracker_sparql_builder_append (preupdate, graph); tracker_sparql_builder_append (preupdate, "> { "); } tracker_sparql_builder_append (preupdate, "_:tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\""); if (graph) { tracker_sparql_builder_append (preupdate, " } "); } tracker_sparql_builder_append (preupdate, " }\n"); tracker_sparql_builder_append (preupdate, "WHERE { FILTER (NOT EXISTS { " "?tag a nao:Tag ; nao:prefLabel \""); tracker_sparql_builder_append (preupdate, escaped); tracker_sparql_builder_append (preupdate, "\" }) }\n"); /* associate file with tag */ tracker_sparql_builder_predicate (metadata, "nao:hasTag"); tracker_sparql_builder_object_variable (metadata, var); g_string_append_printf (where, "?%s a nao:Tag ; nao:prefLabel \"%s\" .\n", var, escaped); g_free (var); g_free (escaped); g_free (p); } g_ptr_array_free (keywords, TRUE); if (xd->publisher) { gchar *uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", xd->publisher); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:Contact"); tracker_sparql_builder_predicate (preupdate, "nco:fullname"); tracker_sparql_builder_object_unvalidated (preupdate, xd->publisher); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nco:creator"); tracker_sparql_builder_object_iri (metadata, uri); g_free (uri); } if (xd->type) { tracker_sparql_builder_predicate (metadata, "dc:type"); tracker_sparql_builder_object_unvalidated (metadata, xd->type); } if (xd->format) { tracker_sparql_builder_predicate (metadata, "dc:format"); tracker_sparql_builder_object_unvalidated (metadata, xd->format); } if (xd->identifier) { tracker_sparql_builder_predicate (metadata, "dc:identifier"); tracker_sparql_builder_object_unvalidated (metadata, xd->identifier); } if (xd->source) { tracker_sparql_builder_predicate (metadata, "dc:source"); tracker_sparql_builder_object_unvalidated (metadata, xd->source); } if (xd->language) { tracker_sparql_builder_predicate (metadata, "dc:language"); tracker_sparql_builder_object_unvalidated (metadata, xd->language); } if (xd->relation) { tracker_sparql_builder_predicate (metadata, "dc:relation"); tracker_sparql_builder_object_unvalidated (metadata, xd->relation); } if (xd->coverage) { tracker_sparql_builder_predicate (metadata, "dc:coverage"); tracker_sparql_builder_object_unvalidated (metadata, xd->coverage); } if (xd->address || xd->state || xd->country || xd->city || xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:location"); tracker_sparql_builder_object_blank_open (metadata); /* GeoLocation */ tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "slo:GeoLocation"); if (xd->address || xd->state || xd->country || xd->city) { gchar *addruri; addruri = tracker_sparql_get_uuid_urn (); tracker_sparql_builder_predicate (metadata, "slo:postalAddress"); tracker_sparql_builder_object_iri (metadata, addruri); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, addruri); g_free (addruri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nco:PostalAddress"); if (xd->address) { tracker_sparql_builder_predicate (preupdate, "nco:streetAddress"); tracker_sparql_builder_object_unvalidated (preupdate, xd->address); } if (xd->state) { tracker_sparql_builder_predicate (preupdate, "nco:region"); tracker_sparql_builder_object_unvalidated (preupdate, xd->state); } if (xd->city) { tracker_sparql_builder_predicate (preupdate, "nco:locality"); tracker_sparql_builder_object_unvalidated (preupdate, xd->city); } if (xd->country) { tracker_sparql_builder_predicate (preupdate, "nco:country"); tracker_sparql_builder_object_unvalidated (preupdate, xd->country); } if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (xd->gps_altitude) { tracker_sparql_builder_predicate (metadata, "slo:altitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_altitude); } if (xd->gps_latitude) { tracker_sparql_builder_predicate (metadata, "slo:latitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_latitude); } if (xd->gps_longitude) { tracker_sparql_builder_predicate (metadata, "slo:longitude"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_longitude); } tracker_sparql_builder_object_blank_close (metadata); /* GeoLocation */ } if (xd->gps_direction) { tracker_sparql_builder_predicate (metadata, "nfo:heading"); tracker_sparql_builder_object_unvalidated (metadata, xd->gps_direction); } if (gd.width) { tracker_sparql_builder_predicate (metadata, "nfo:width"); tracker_sparql_builder_object_unvalidated (metadata, gd.width); g_free (gd.width); } if (gd.height) { tracker_sparql_builder_predicate (metadata, "nfo:height"); tracker_sparql_builder_object_unvalidated (metadata, gd.height); g_free (gd.height); } if (gd.comment) { tracker_sparql_builder_predicate (metadata, "nie:comment"); tracker_sparql_builder_object_unvalidated (metadata, gd.comment); g_free (gd.comment); } tracker_xmp_free (xd); }