[tracker] TrackerExtractDecorator: Add priority dbus interface



commit 263870c3a8f76064a8ebe4e07a54b6241aa58ffc
Author: Xavier Claessens <xavier claessens collabora co uk>
Date:   Mon Jan 27 15:20:02 2014 -0500

    TrackerExtractDecorator: Add priority dbus interface
    
    That dbus interface lets application tell tracker-extract which
    rdf:type must be extracted in priority. For example, when the user
    interacts with the music player, they want to give the priority to
    "nfo:Audio" files.
    
    This commit only introduces the DBus machinary, not the actual
    implementation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=719802

 data/dbus/Makefile.am                           |    1 +
 data/dbus/tracker-extract-priority.xml          |   10 +
 src/libtracker-miner/tracker-decorator.c        |    9 +
 src/libtracker-miner/tracker-decorator.h        |    3 +
 src/tracker-extract/.gitignore                  |    4 +
 src/tracker-extract/Makefile.am                 |   24 +++
 src/tracker-extract/tracker-extract-decorator.c |  241 +++++++++++++++++++++--
 7 files changed, 275 insertions(+), 17 deletions(-)
---
diff --git a/data/dbus/Makefile.am b/data/dbus/Makefile.am
index a1717eb..e632c48 100644
--- a/data/dbus/Makefile.am
+++ b/data/dbus/Makefile.am
@@ -5,6 +5,7 @@ configdir = $(datadir)/tracker
 config_DATA = \
        tracker-backup.xml \
        tracker-extract.xml \
+       tracker-extract-priority.xml \
        tracker-miner.xml \
        tracker-miner-web.xml \
        tracker-resources.xml \
diff --git a/data/dbus/tracker-extract-priority.xml b/data/dbus/tracker-extract-priority.xml
new file mode 100644
index 0000000..729c454
--- /dev/null
+++ b/data/dbus/tracker-extract-priority.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/">
+  <interface name="org.freedesktop.Tracker1.Extract.Priority">
+    <method name="SetRdfTypes">
+      <arg type="as" name="rdf_types" direction="in" />
+    </method>
+    <property name="SupportedRdfTypes" type="as" access="read" />
+  </interface>
+</node>
diff --git a/src/libtracker-miner/tracker-decorator.c b/src/libtracker-miner/tracker-decorator.c
index 7caf1c2..bd8747e 100644
--- a/src/libtracker-miner/tracker-decorator.c
+++ b/src/libtracker-miner/tracker-decorator.c
@@ -1257,6 +1257,15 @@ tracker_decorator_next_finish (TrackerDecorator  *decorator,
        return g_task_propagate_pointer (G_TASK (result), error);
 }
 
+void
+tracker_decorator_set_priority_rdf_types (TrackerDecorator    *decorator,
+                                          const gchar * const *rdf_types)
+{
+       g_return_if_fail (TRACKER_DECORATOR (decorator));
+
+       /* FIXME: Not Implemented */
+}
+
 /**
  * tracker_decorator_info_get_urn:
  * @info: a #TrackerDecoratorInfo.
diff --git a/src/libtracker-miner/tracker-decorator.h b/src/libtracker-miner/tracker-decorator.h
index 5317555..5677700 100644
--- a/src/libtracker-miner/tracker-decorator.h
+++ b/src/libtracker-miner/tracker-decorator.h
@@ -88,6 +88,9 @@ TrackerDecoratorInfo *
                                                    GAsyncResult         *result,
                                                    GError              **error);
 
+void          tracker_decorator_set_priority_rdf_types (TrackerDecorator    *decorator,
+                                                        const gchar * const *rdf_types);
+
 GType         tracker_decorator_info_get_type     (void) G_GNUC_CONST;
 
 TrackerDecoratorInfo *
diff --git a/src/tracker-extract/.gitignore b/src/tracker-extract/.gitignore
index 95a4828..9765d48 100644
--- a/src/tracker-extract/.gitignore
+++ b/src/tracker-extract/.gitignore
@@ -1 +1,5 @@
 tracker-extract
+tracker-extract-priority-dbus-stamp
+tracker-extract-priority-dbus.c
+tracker-extract-priority-dbus.h
+
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index 0bcd130..7bce8ae 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -529,6 +529,8 @@ tracker_extract_SOURCES = \
        tracker-extract.h \
        tracker-extract-decorator.c \
        tracker-extract-decorator.h \
+       tracker-extract-priority-dbus.c \
+       tracker-extract-priority-dbus.h \
        tracker-read.c \
        tracker-read.h \
        tracker-main.c \
@@ -553,5 +555,27 @@ if HAVE_LIBSTREAMANALYZER
 tracker_extract_SOURCES += tracker-topanalyzer.cpp tracker-topanalyzer.h
 endif
 
+# do nothing, output as a side-effect
+tracker-extract-priority-dbus.c: tracker-extract-priority-dbus-stamp
+       @:
+
+tracker-extract-priority-dbus.h: tracker-extract-priority-dbus-stamp
+       @:
+
+tracker-extract-priority-dbus-stamp: Makefile.am $(top_srcdir)/data/dbus/tracker-extract-priority.xml
+       gdbus-codegen --interface-prefix org.freedesktop.Tracker1.Extract. \
+                     --generate-c-code tracker-extract-priority-dbus \
+                     --c-namespace TrackerExtractDBus \
+                     $(top_srcdir)/data/dbus/tracker-extract-priority.xml
+       touch $@
+
+BUILT_SOURCES = \
+       tracker-extract-priority-dbus.c \
+       tracker-extract-priority-dbus.h \
+       tracker-extract-priority-dbus-stamp \
+       $(NULL)
+
+CLEANFILES = $(BUILT_SOURCES)
+
 EXTRA_DIST = \
        $(rules_files)
diff --git a/src/tracker-extract/tracker-extract-decorator.c b/src/tracker-extract/tracker-extract-decorator.c
index abd72c0..163c9af 100644
--- a/src/tracker-extract/tracker-extract-decorator.c
+++ b/src/tracker-extract/tracker-extract-decorator.c
@@ -22,6 +22,7 @@
 #include <libtracker-extract/tracker-extract.h>
 #include <libtracker-common/tracker-ontologies.h>
 #include "tracker-extract-decorator.h"
+#include "tracker-extract-priority-dbus.h"
 
 enum {
        PROP_EXTRACTOR = 1
@@ -44,13 +45,38 @@ struct _TrackerExtractDecoratorPrivate {
        TrackerExtract *extractor;
        GTimer *timer;
        guint n_extracting_files;
+
+       /* DBus name -> AppData */
+       GHashTable *apps;
+       TrackerExtractDBusPriority *iface;
 };
 
-static void decorator_get_next_file (TrackerDecorator *decorator);
+typedef struct {
+       guint watch_id;
+       gchar **rdf_types;
+} AppData;
+
+/* Preferably classes with tracker:notify true, if an
+ * extractor module handles new ones, it must be added
+ * here.
+ */
+static const gchar *supported_classes[] = {
+       "nfo:Document",
+       "nfo:Audio",
+       "nfo:Image",
+       "nfo:Video",
+       "nfo:FilesystemImage",
+       NULL
+};
 
+static GInitableIface *parent_initable_iface;
 
-G_DEFINE_TYPE (TrackerExtractDecorator, tracker_extract_decorator,
-               TRACKER_TYPE_DECORATOR_FS)
+static void decorator_get_next_file (TrackerDecorator *decorator);
+static void tracker_extract_decorator_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (TrackerExtractDecorator, tracker_extract_decorator,
+                        TRACKER_TYPE_DECORATOR_FS,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, 
tracker_extract_decorator_initable_iface_init))
 
 static void
 tracker_extract_decorator_get_property (GObject    *object,
@@ -99,6 +125,9 @@ tracker_extract_decorator_finalize (GObject *object)
        if (priv->timer)
                g_timer_destroy (priv->timer);
 
+       g_object_unref (priv->iface);
+       g_hash_table_unref (priv->apps);
+
        G_OBJECT_CLASS (tracker_extract_decorator_parent_class)->finalize (object);
 }
 
@@ -306,6 +335,136 @@ tracker_extract_decorator_finished (TrackerDecorator *decorator)
        g_free (time_str);
 }
 
+static gboolean
+strv_contains (const gchar * const *strv,
+               const gchar         *needle)
+{
+       guint i;
+
+       for (i = 0; strv[i] != NULL; i++) {
+               if (g_str_equal (strv[i], needle))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void
+string_array_add (GPtrArray   *array,
+                  const gchar *str)
+{
+       guint i;
+
+       for (i = 0; i < array->len; i++) {
+               if (g_str_equal (g_ptr_array_index (array, i), str))
+                       return;
+       }
+
+       g_ptr_array_add (array, (gchar *) str);
+}
+
+static void
+priority_changed (TrackerExtractDecorator *decorator)
+{
+       TrackerExtractDecoratorPrivate *priv;
+       GPtrArray                      *array;
+       GHashTableIter                  iter;
+       gpointer                        value;
+
+       priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv;
+
+       /* Construct an strv removing dups */
+       array = g_ptr_array_new ();
+       g_hash_table_iter_init (&iter, priv->apps);
+       while (g_hash_table_iter_next (&iter, NULL, &value)) {
+               AppData *data = value;
+               guint i;
+
+               for (i = 0; data->rdf_types[i] != NULL; i++) {
+                       string_array_add (array, data->rdf_types[i]);
+               }
+       }
+       g_ptr_array_add (array, NULL);
+
+       tracker_decorator_set_priority_rdf_types (TRACKER_DECORATOR (decorator),
+                                                 (const gchar * const *) array->pdata);
+
+       g_ptr_array_unref (array);
+}
+
+static void
+app_data_destroy (AppData *data)
+{
+       g_bus_unwatch_name (data->watch_id);
+       g_strfreev (data->rdf_types);
+       g_slice_free (AppData, data);
+}
+
+static void
+name_vanished_cb (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+       TrackerExtractDecorator        *decorator = user_data;
+       TrackerExtractDecoratorPrivate *priv;
+
+       priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv;
+       g_hash_table_remove (priv->apps, name);
+       priority_changed (decorator);
+}
+
+static gboolean
+handle_set_rdf_types_cb (TrackerExtractDBusPriority *iface,
+                         GDBusMethodInvocation      *invocation,
+                         const gchar * const        *rdf_types,
+                         TrackerExtractDecorator    *decorator)
+{
+       TrackerExtractDecoratorPrivate *priv;
+       const gchar *sender;
+       GDBusConnection *conn;
+       AppData *data;
+       guint i;
+
+       priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv;
+       sender = g_dbus_method_invocation_get_sender (invocation);
+       conn = g_dbus_method_invocation_get_connection (invocation);
+
+       /* Verify all types are supported */
+       for (i = 0; rdf_types[i] != NULL; i++) {
+               if (!strv_contains (supported_classes, rdf_types[i])) {
+                       g_dbus_method_invocation_return_error (invocation,
+                                                              TRACKER_DBUS_ERROR,
+                                                              TRACKER_DBUS_ERROR_ASSERTION_FAILED,
+                                                              "Unsupported rdf:type %s",
+                                                              rdf_types[i]);
+                       return TRUE;
+               }
+       }
+
+       data = g_hash_table_lookup (priv->apps, sender);
+       if (data == NULL) {
+               data = g_slice_new0 (AppData);
+               data->watch_id = g_bus_watch_name_on_connection (conn,
+                                                                sender,
+                                                                G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                                NULL,
+                                                                name_vanished_cb,
+                                                                decorator, NULL);
+               g_hash_table_insert (priv->apps,
+                                    g_strdup (sender),
+                                    data);
+       } else {
+               g_strfreev (data->rdf_types);
+       }
+
+       data->rdf_types = g_strdupv ((GStrv) rdf_types);
+       priority_changed (decorator);
+
+       tracker_extract_dbus_priority_complete_set_rdf_types (iface, invocation);
+
+       return TRUE;
+}
+
 static void
 tracker_extract_decorator_class_init (TrackerExtractDecoratorClass *klass)
 {
@@ -342,29 +501,77 @@ tracker_extract_decorator_init (TrackerExtractDecorator *decorator)
        decorator->priv = TRACKER_EXTRACT_DECORATOR_GET_PRIVATE (decorator);
 }
 
+static gboolean
+tracker_extract_decorator_initable_init (GInitable     *initable,
+                                         GCancellable  *cancellable,
+                                         GError       **error)
+{
+       TrackerExtractDecorator        *decorator;
+       TrackerExtractDecoratorPrivate *priv;
+       GDBusConnection                *conn;
+       gboolean                        ret = TRUE;
+
+       decorator = TRACKER_EXTRACT_DECORATOR (initable);
+       priv = decorator->priv;
+
+       priv->apps = g_hash_table_new_full (g_str_hash,
+                                           g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify) app_data_destroy);
+
+       priv->iface = tracker_extract_dbus_priority_skeleton_new ();
+       g_signal_connect (priv->iface, "handle-set-rdf-types",
+                         G_CALLBACK (handle_set_rdf_types_cb),
+                         decorator);
+
+       tracker_extract_dbus_priority_set_supported_rdf_types (priv->iface,
+                                                              supported_classes);
+
+       conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+       if (conn == NULL) {
+               ret = FALSE;
+               goto out;
+       }
+
+       if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->iface),
+                                              conn,
+                                              "/org/freedesktop/Tracker1/Extract/Priority",
+                                              error)) {
+               ret = FALSE;
+               goto out;
+       }
+
+       /* Chainup to parent's init last, to have a chance to export our
+        * DBus interface before RequestName returns. Otherwise our iface
+        * won't be ready by the time the tracker-extract appear on the bus. */
+       if (!parent_initable_iface->init (initable, cancellable, error)) {
+               ret = FALSE;
+               goto out;
+       }
+
+out:
+       g_clear_object (&conn);
+
+       return ret;
+}
+
+static void
+tracker_extract_decorator_initable_iface_init (GInitableIface *iface)
+{
+       parent_initable_iface = g_type_interface_peek_parent (iface);
+       iface->init = tracker_extract_decorator_initable_init;
+}
+
 TrackerDecorator *
 tracker_extract_decorator_new (TrackerExtract  *extract,
                                GCancellable    *cancellable,
                                GError         **error)
 {
-       /* Preferably classes with tracker:notify true, if an
-        * extractor module handles new ones, it must be added
-        * here.
-        */
-       gchar *classes[] = {
-               "nfo:Document",
-               "nfo:Audio",
-               "nfo:Image",
-               "nfo:Video",
-               "nfo:FilesystemImage",
-               NULL
-       };
-
        return g_initable_new (TRACKER_TYPE_EXTRACT_DECORATOR,
                               cancellable, error,
                               "name", "Extract",
                               "data-source", TRACKER_EXTRACT_DATA_SOURCE,
-                              "class-names", classes,
+                              "class-names", supported_classes,
                               "extractor", extract,
                               NULL);
 }


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