Commit d8f89c06 authored by Sumaid Syed's avatar Sumaid Syed
parents 6f802773 ad3bff34
......@@ -62,7 +62,7 @@ endif
custom_target('tracker-miners-compile-schemas',
output: 'gschemas.compiled',
command: [find_program('glib-compile-schemas'), meson.current_build_dir()],
command: [glib_compile_schemas, meson.current_build_dir()],
build_by_default: true,
depends: compile_schemas_deps)
......
......@@ -73,6 +73,7 @@ glib = dependency('glib-2.0', version: '>=' + glib_required)
gmodule = dependency('gmodule-2.0', version: '>=' + glib_required)
gobject = dependency('gobject-2.0', version: '>=' + glib_required)
gstreamer = dependency('gstreamer-1.0', required: false)
gstreamer_audio = dependency('gstreamer-audio-1.0', required: false)
gstreamer_pbutils = dependency('gstreamer-pbutils-1.0', required: false)
gstreamer_tag = dependency('gstreamer-tag-1.0', required: false)
gupnp_dlna = dependency('gupnp-dlna-2.0', version: '>= 0.9.4', required: false)
......@@ -92,7 +93,6 @@ libtiff = dependency('libtiff-4', required: get_option('tiff'))
libxml2 = dependency('libxml-2.0', version: '>= 2.6', required: get_option('xml'))
libvorbis = dependency('vorbisfile', version: '>= 0.22', required: get_option('vorbis'))
poppler = dependency('poppler-glib', version: '>= 0.16.0', required: get_option('pdf'))
taglib = dependency('taglib_c', version: '>= 1.6', required: get_option('taglib'))
totem_plparser = dependency('totem-plparser', required: get_option('playlist'))
upower = dependency('upower-glib', version: '>= 0.9.0', required: false)
zlib = dependency('zlib')
......@@ -386,6 +386,7 @@ configinc = include_directories('./')
srcinc = include_directories('src/')
tracker_internal_libs_dir = join_paths(get_option('prefix'), get_option('libdir'), 'tracker-miners-' + tracker_api_version)
tracker_install_rpath = ':'.join([tracker_internal_libs_dir, libdir])
tracker_extract_modules_dir = join_paths(get_option('prefix'), get_option('libdir'), 'tracker-miners-@0@/extract-modules'.format(tracker_api_version))
# NOTE: We don't use ${TRACKER_API_VERSION} because other content like
......@@ -399,6 +400,7 @@ tracker_uninstalled_writeback_modules_dir = join_paths(meson.current_build_dir()
gsettings_schema_dir = join_paths(get_option('prefix'), get_option('datadir'), 'glib-2.0', 'schemas')
glib_compile_schemas = find_program('glib-compile-schemas')
glib_mkenums = find_program('glib-mkenums')
subdir('src')
......@@ -417,6 +419,8 @@ subdir('tests')
subdir('po')
meson.add_install_script('meson_integration_commands.sh', glib_compile_schemas.path(), gsettings_schema_dir)
summary = [
'\nBuild Configuration:',
' Prefix: ' + get_option('prefix'),
......@@ -469,7 +473,7 @@ endif
if have_tracker_writeback
summary += [
'\nWriteback Formats:',
' Audio files using Taglib: ' + taglib.found().to_string(),
' Audio files using GStreamer: ' + (gstreamer.found() and gstreamer_tag.found() and gstreamer_audio.found()).to_string(),
' XMP: ' + exempi.found().to_string(),
]
endif
......
#!/bin/sh
# Post install triggers.
#
# These are needed when following the developer workflow that we suggest in
# README.md, of installing into an isolated prefix like ~/opt/tracker.
set -e
GLIB_COMPILE_SCHEMAS=$1
GSETTINGS_SCHEMAS_DIR=$2
if [ -z "$DESTDIR" ]; then
$GLIB_COMPILE_SCHEMAS $GSETTINGS_SCHEMAS_DIR
fi
......@@ -57,8 +57,6 @@ option('png', type: 'feature', value: 'auto',
description: 'Support extracting metadata from PNG images')
option('raw', type: 'feature', value: 'auto',
description: 'Support extracting metadata from RAW photos')
option('taglib', type: 'feature', value: 'auto',
description: 'Support writeback for audio files using Taglib')
option('tiff', type: 'feature', value: 'auto',
description: 'Support extracting metadata from TIFF images')
option('vorbis', type: 'feature', value: 'auto',
......
......@@ -4,6 +4,7 @@
#
ar
as
be
be@latin
bg
bs
......
This diff is collapsed.
......@@ -21,7 +21,6 @@ tracker_miners_common_sources = [
enums[0], enums[1],
]
# FIXME: need to link against -lkvm on OpenBSD, see configure.ac
tracker_miners_common_dependencies = [glib, gio, gio_unix, libmath]
tracker_miners_common_private_dependencies = [charset_library]
......@@ -30,7 +29,7 @@ if libseccomp.found()
endif
libtracker_miners_common = library('tracker-miners-common',
libtracker_miners_common = static_library('tracker-miners-common',
tracker_miners_common_sources,
dependencies: tracker_miners_common_dependencies + tracker_miners_common_private_dependencies,
c_args: tracker_c_args,
......@@ -39,15 +38,6 @@ libtracker_miners_common = library('tracker-miners-common',
commoninc = include_directories('.')
# This dependency can't be used everywhere right now. The issue is that if
# every other library depends on this one, we end up with a combinatorial
# explosion that results in the link line for src/tracker/tracker being
# nearly 200,000 characters long which causes this kind of error:
#
# Linking target src/tracker/tracker
# ninja: fatal: posix_spawn: Argument list too long
#
# Upstream issue: https://github.com/mesonbuild/meson/issues/671
tracker_miners_common_dep = declare_dependency(
sources: [tracker_miners_common_enum_header],
link_with: libtracker_miners_common,
......
......@@ -31,7 +31,7 @@ executable('tracker-miner-fs', sources,
c_args: tracker_c_args,
install: true,
install_dir: get_option('libexecdir'),
install_rpath: tracker_internal_libs_dir,
install_rpath: tracker_install_rpath,
)
dbus_service_file_untranslated = configure_file(
......
......@@ -170,10 +170,10 @@ tracker_power_finalize (GObject *object)
priv = GET_PRIV (object);
#ifndef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY
g_object_unref (priv->composite_device);
g_clear_object (&priv->composite_device);
#endif /* HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */
g_object_unref (priv->client);
g_clear_object (&priv->client);
(G_OBJECT_CLASS (tracker_power_parent_class)->finalize) (object);
}
......
......@@ -374,7 +374,7 @@ writeback_dispatcher_writeback_file (TrackerMinerFS *fs,
data->retry_timeout = 0;
data->self = self;
g_object_weak_ref (G_OBJECT (data->self), self_weak_notify, data);
data->fs = g_object_ref (fs);
data->fs = TRACKER_MINER_FILES (g_object_ref (fs));
data->file = g_object_ref (file);
data->results = g_ptr_array_ref (results);
data->rdf_types = g_strdupv (rdf_types);
......
......@@ -8,7 +8,7 @@ executable('tracker-miner-rss', sources,
c_args: tracker_c_args,
install: true,
install_dir: get_option('libexecdir'),
install_rpath: tracker_internal_libs_dir,
install_rpath: tracker_install_rpath,
)
dbus_service_file_untranslated = configure_file(
......
......@@ -167,7 +167,7 @@ executable('tracker-extract',
dependencies: tracker_extract_dependencies,
install: true,
install_dir: join_paths(get_option('prefix'), get_option('libexecdir')),
install_rpath: tracker_internal_libs_dir)
install_rpath: tracker_install_rpath)
dbus_service_file_untranslated = configure_file(
input: 'org.freedesktop.Tracker1.Miner.Extract.service.in.in',
......
......@@ -6,8 +6,8 @@
modules = []
if taglib.found()
modules += [['writeback-taglib', 'tracker-writeback-taglib.c', [tracker_miner, tracker_sparql, tracker_miners_common_dep, taglib]]]
if gstreamer.found() and gstreamer_tag.found() and gstreamer_audio.found()
modules += [['writeback-gstreamer', 'tracker-writeback-gstreamer.c', [tracker_miner, tracker_sparql, tracker_miners_common_dep, gstreamer, gstreamer_tag]]]
endif
if exempi.found()
......@@ -47,7 +47,7 @@ executable('tracker-writeback',
dependencies: [gmodule, tracker_miner, tracker_sparql, tracker_miners_common_dep],
install: true,
install_dir: join_paths(get_option('prefix'), get_option('libexecdir')),
install_rpath: tracker_internal_libs_dir)
install_rpath: tracker_install_rpath)
dbus_service_file = configure_file(
input: 'org.freedesktop.Tracker1.Writeback.service.in',
......
......@@ -224,15 +224,16 @@ tracker_writeback_file_update_metadata (TrackerWriteback *writeback,
}
if (!retval) {
g_set_error (error,
TRACKER_DBUS_ERROR,
TRACKER_DBUS_ERROR_UNSUPPORTED,
"Module does not support writeback for %s",
mime_type);
/* module does not support writeback for this file */
g_object_unref (file_info);
g_object_unref (file);
g_set_error_literal (error,
TRACKER_DBUS_ERROR,
TRACKER_DBUS_ERROR_UNSUPPORTED,
"Module does not support writeback for this file");
return FALSE;
}
......
This diff is collapsed.
/*
* Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <taglib/tag_c.h>
#include <glib-object.h>
#include <libtracker-sparql/tracker-ontologies.h>
#include "tracker-writeback-file.h"
#define TRACKER_TYPE_WRITEBACK_TAGLIB (tracker_writeback_taglib_get_type ())
typedef struct TrackerWritebackTaglib TrackerWritebackTaglib;
typedef struct TrackerWritebackTaglibClass TrackerWritebackTaglibClass;
struct TrackerWritebackTaglib {
TrackerWritebackFile parent_instance;
};
struct TrackerWritebackTaglibClass {
TrackerWritebackFileClass parent_class;
};
static GType tracker_writeback_taglib_get_type (void) G_GNUC_CONST;
static gboolean writeback_taglib_update_file_metadata (TrackerWritebackFile *wbf,
GFile *file,
GPtrArray *values,
TrackerSparqlConnection *connection,
GCancellable *cancellable,
GError **error);
static const gchar * const *writeback_taglib_content_types (TrackerWritebackFile *wbf);
static gchar* writeback_taglib_get_artist_name (TrackerSparqlConnection *connection,
const gchar *urn);
static gchar* writeback_taglib_get_album_name (TrackerSparqlConnection *connection,
const gchar *urn);
G_DEFINE_DYNAMIC_TYPE (TrackerWritebackTaglib, tracker_writeback_taglib, TRACKER_TYPE_WRITEBACK_FILE);
static void
tracker_writeback_taglib_class_init (TrackerWritebackTaglibClass *klass)
{
TrackerWritebackFileClass *writeback_file_class = TRACKER_WRITEBACK_FILE_CLASS (klass);
writeback_file_class->update_file_metadata = writeback_taglib_update_file_metadata;
writeback_file_class->content_types = writeback_taglib_content_types;
}
static void
tracker_writeback_taglib_class_finalize (TrackerWritebackTaglibClass *klass)
{
}
static void
tracker_writeback_taglib_init (TrackerWritebackTaglib *wbt)
{
}
static const gchar * const *
writeback_taglib_content_types (TrackerWritebackFile *wbf)
{
static const gchar *content_types [] = {
"audio/x-mpc",
"audio/x-musepack",
"audio/mpc",
"audio/musepack",
"audio/mpeg",
"audio/x-mpeg",
"audio/mp3",
"audio/x-mp3",
"audio/mpeg3",
"audio/x-mpeg3",
"audio/mpg",
"audio/x-mpg",
"audio/x-mpegaudio",
"audio/flac",
"audio/mp4",
"audio/asf",
"application/asx",
"video/x-ms-asf-plugin",
"application/x-mplayer2",
"video/x-ms-asf",
"application/vnd.ms-asf",
"video/x-ms-asf-plugin",
"video/x-ms-wm",
"video/x-ms-wmx",
"audio/aiff",
"audio/x-aiff",
"sound/aiff",
"audio/rmf",
"audio/x-rmf",
"audio/x-pn-aiff",
"audio/x-gsm",
"audio/mid",
"audio/x-midi",
"audio/vnd.qcelp",
"audio/wav",
"audio/x-wav",
"audio/wave",
"audio/x-pn-wav",
"audio/tta",
"audio/x-tta",
"audio/ogg",
"application/ogg",
"audio/x-ogg",
"application/x-ogg",
"audio/x-speex",
NULL
};
return content_types;
}
static gboolean
writeback_taglib_update_file_metadata (TrackerWritebackFile *writeback_file,
GFile *file,
GPtrArray *values,
TrackerSparqlConnection *connection,
GCancellable *cancellable,
GError **error)
{
gboolean ret;
gchar *path;
TagLib_File *taglib_file = NULL;
TagLib_Tag *tag;
guint n;
ret = FALSE;
path = g_file_get_path (file);
taglib_file = taglib_file_new (path);
if (!taglib_file || !taglib_file_is_valid (taglib_file)) {
goto out;
}
tag = taglib_file_tag (taglib_file);
for (n = 0; n < values->len; n++) {
const GStrv row = g_ptr_array_index (values, n);
if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "title") == 0) {
taglib_tag_set_title (tag, row[3]);
}
if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "performer") == 0) {
gchar *artist_name = writeback_taglib_get_artist_name (connection, row[3]);
if (artist_name) {
taglib_tag_set_artist (tag, artist_name);
g_free (artist_name);
}
}
if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "musicAlbum") == 0) {
gchar *album_name = writeback_taglib_get_album_name (connection, row[3]);
if (album_name) {
taglib_tag_set_album (tag, album_name);
g_free (album_name);
}
}
if (g_strcmp0 (row[2], TRACKER_PREFIX_RDFS "comment") == 0) {
taglib_tag_set_comment (tag, row[3]);
}
if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "genre") == 0) {
taglib_tag_set_genre (tag, row[3]);
}
if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "trackNumber") == 0) {
taglib_tag_set_track (tag, atoi (row[3]));
}
}
taglib_file_save (taglib_file);
ret = TRUE;
out:
g_free (path);
if (taglib_file) {
taglib_file_free (taglib_file);
}
return ret;
}
static gchar*
writeback_taglib_get_from_query (TrackerSparqlConnection *connection,
const gchar *urn,
const gchar *query,
const gchar *errmsg)
{
TrackerSparqlCursor *cursor;
GError *error = NULL;
gchar *value = NULL;
cursor = tracker_sparql_connection_query (connection,
query,
NULL,
&error);
if (error || !cursor || !tracker_sparql_cursor_next (cursor, NULL, NULL)) {
g_warning ("Couldn't find %s for artist with urn '%s', %s",
errmsg,
urn,
error ? error->message : "no such was found");
if (error) {
g_error_free (error);
}
} else {
value = g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL));
}
g_object_unref (cursor);
return value;
}
static gchar*
writeback_taglib_get_artist_name (TrackerSparqlConnection *connection,
const gchar *urn)
{
gchar *val, *query;
query = g_strdup_printf ("SELECT ?artistName WHERE {<%s> nmm:artistName ?artistName}",
urn);
val = writeback_taglib_get_from_query (connection, urn, query, "artist name");
g_free (query);
return val;
}
static gchar*
writeback_taglib_get_album_name (TrackerSparqlConnection *connection,
const gchar *urn)
{
gchar *val, *query;
query = g_strdup_printf ("SELECT ?albumName WHERE {<%s> dc:title ?albumName}",
urn);
val = writeback_taglib_get_from_query (connection, urn, query, "album name");
g_free (query);
return val;
}
TrackerWriteback *
writeback_module_create (GTypeModule *module)
{
tracker_writeback_taglib_register_type (module);
return g_object_new (TRACKER_TYPE_WRITEBACK_TAGLIB, NULL);
}
const gchar * const *
writeback_module_get_rdf_types (void)
{
static const gchar *rdftypes[] = {
TRACKER_PREFIX_NFO "Audio",
NULL
};
return rdftypes;
}
......@@ -17,23 +17,23 @@
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
"""
Write values in tracker and check the actual values are written
on the files. Note that these tests are highly platform dependant.
"""
"""Tests for Tracker writeback daemon."""
import os
import sys
import time
from common.utils.extractor import get_tracker_extract_jsonld_output
from common.utils.helpers import log
from common.utils.writebacktest import CommonTrackerWritebackTest as CommonTrackerWritebackTest
from common.utils.writebacktest import CommonTrackerWritebackTest
import unittest as ut
REASONABLE_TIMEOUT = 5 # Seconds we wait for tracker-writeback to do the work
class WritebackBasicDataTest (CommonTrackerWritebackTest):
class WritebackImagesTest (CommonTrackerWritebackTest):
"""
Write in tracker store the properties witih writeback support and check
that the new values are actually in the file
......@@ -50,9 +50,8 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
the @prop is used.
"""
# FIXME: filename is actually a URI! :(
filename_real = filename[len('file://'):]
initial_mtime = os.stat(filename_real).st_mtime
path = self.prepare_test_image(self.datadir_path(filename))
initial_mtime = path.stat().st_mtime
TEST_VALUE = prop.replace(":", "") + "test"
SPARQL_TMPL = """
......@@ -60,13 +59,13 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
INSERT { ?u %s '%s' }
WHERE { ?u nie:url '%s' }
"""
self.tracker.update(SPARQL_TMPL % (prop, filename, prop, prop, TEST_VALUE, filename))
self.tracker.update(SPARQL_TMPL % (prop, path.as_uri(), prop, prop, TEST_VALUE, path.as_uri()))
log("Waiting for change on %s" % filename_real)
self.wait_for_file_change(filename_real, initial_mtime)
log("Waiting for change on %s" % path)
self.wait_for_file_change(path, initial_mtime)
log("Got the change")
results = get_tracker_extract_jsonld_output(filename, mimetype)
results = get_tracker_extract_jsonld_output(path, mimetype)
keyDict = expectedKey or prop
self.assertIn(TEST_VALUE, results[keyDict])
......@@ -102,12 +101,10 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
# JPEG test
def test_001_jpeg_title(self):
#FILENAME = "test-writeback-monitored/writeback-test-1.jpeg"
self.__writeback_test(self.get_test_filename_jpeg(), "image/jpeg", "nie:title")
self.__writeback_test("writeback-test-1.jpeg", "image/jpeg", "nie:title")
def test_002_jpeg_description(self):
#FILENAME = "test-writeback-monitored/writeback-test-1.jpeg"
self.__writeback_test(self.get_test_filename_jpeg(), "image/jpeg", "nie:description")
self.__writeback_test("writeback-test-1.jpeg", "image/jpeg", "nie:description")
# def test_003_jpeg_keyword (self):
# #FILENAME = "test-writeback-monitored/writeback-test-1.jpeg"
......@@ -121,12 +118,10 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
# TIFF tests
def test_011_tiff_title(self):
#FILANAME = "test-writeback-monitored/writeback-test-2.tif"
self.__writeback_test(self.get_test_filename_tiff(), "image/tiff", "nie:title")
self.__writeback_test("writeback-test-2.tif", "image/tiff", "nie:title")
def test_012_tiff_description(self):
FILENAME = "test-writeback-monitored/writeback-test-2.tif"
self.__writeback_test(self.get_test_filename_tiff(), "image/tiff", "nie:description")
self.__writeback_test("writeback-test-2.tif", "image/tiff", "nie:description")
# def test_013_tiff_keyword (self):
# FILENAME = "test-writeback-monitored/writeback-test-2.tif"
......@@ -140,12 +135,10 @@ class WritebackBasicDataTest (CommonTrackerWritebackTest):
# PNG tests
def test_021_png_title(self):
FILENAME = "test-writeback-monitored/writeback-test-4.png"
self.__writeback_test(self.get_test_filename_png(), "image/png", "nie:title")
self.__writeback_test("writeback-test-4.png", "image/png", "nie:title")
def test_022_png_description(self):
FILENAME = "test-writeback-monitored/writeback-test-4.png"
self.__writeback_test(self.get_test_filename_png(), "image/png", "nie:description")
self.__writeback_test("writeback-test-4.png", "image/png", "nie:description")
# def test_023_png_keyword (self):
# FILENAME = "test-writeback-monitored/writeback-test-4.png"
......
......@@ -52,6 +52,10 @@ class WritebackKeepDateTest (CommonTrackerWritebackTest):
"""
NB#217627 - Order if results is different when an image is marked as favorite.
"""
jpeg_path = self.prepare_test_image(self.datadir_path('writeback-test-1.jpeg'))
tif_path = self.prepare_test_image(self.datadir_path('writeback-test-2.tif'))
png_path = self.prepare_test_image(self.datadir_path('writeback-test-4.png'))
query_images = """
SELECT nie:url(?u) ?contentCreated WHERE {
?u a nfo:Visual ;
......@@ -64,10 +68,7 @@ class WritebackKeepDateTest (CommonTrackerWritebackTest):
log("Waiting 2 seconds to ensure there is a noticiable difference in the timestamp")
time.sleep(2)
url = self.get_test_filename_jpeg()
filename = url[len('file://'):]
initial_mtime = os.stat(filename).st_mtime
initial_mtime = jpeg_path.stat().st_mtime
# This triggers the writeback
mark_as_favorite = """
......@@ -76,14 +77,14 @@ class WritebackKeepDateTest (CommonTrackerWritebackTest):
} WHERE {
?u nie:url <%s> .
}
""" % url
""" % jpeg_path.as_uri()
self.tracker.update(mark_as_favorite)
log("Setting favorite in <%s>" % url)
log("Setting favorite in <%s>" % jpeg_path.as_uri())
self.wait_for_file_change(filename, initial_mtime)
self.wait_for_file_change(jpeg_path, initial_mtime)
# Check the value is written in the file
metadata = get_tracker_extract_jsonld_output(filename, "")
metadata = get_tracker_extract_jsonld_output(jpeg_path, "")
tags = metadata.get('nao:hasTag', [])
tag_names = [tag['nao:prefLabel'] for tag in tags]
......
#!/usr/bin/env python3
# Copyright (C) 2019, Sam Thursfield (sam@afuera.me.uk)
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
import unittest