summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2015-09-25 10:36:14 -0400
committerXavier Claessens <xavier.claessens@collabora.com>2015-11-03 13:13:45 -0500
commite23b0fa5f6656d53b977693bf55174bd2ccd172d (patch)
tree15a5e16b725fb7a4dde96a0d3142b7229495bdcc
parent93b4ef94c0fcc0d02aa1ac810286d016b516417f (diff)
downloadgrilo-plugins-e23b0fa5f6656d53b977693bf55174bd2ccd172d.tar.gz
tracker: rewrite notification codebaserock/grilo-plugins-0.2.16-17-ge23b0fa
The GrlMedia object passed to "content-changed" signal was useless because it didn't even contain an URL. To have at least that bare minimum information we have to query tracker for all subjects when we receive GraphUpdated. https://bugzilla.gnome.org/show_bug.cgi?id=746974
-rw-r--r--src/tracker/grl-tracker-source-notif.c739
-rw-r--r--src/tracker/grl-tracker-source-notif.h3
-rw-r--r--src/tracker/grl-tracker.c1
3 files changed, 273 insertions, 470 deletions
diff --git a/src/tracker/grl-tracker-source-notif.c b/src/tracker/grl-tracker-source-notif.c
index beabf6b..4b35e0e 100644
--- a/src/tracker/grl-tracker-source-notif.c
+++ b/src/tracker/grl-tracker-source-notif.c
@@ -1,11 +1,13 @@
/*
* Copyright (C) 2011-2012 Igalia S.L.
* Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2015 Collabora Ltd.
*
* Contact: Iago Toral Quiroga <itoral@igalia.com>
*
* Authors: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
* Juan A. Suarez Romero <jasuarez@igalia.com>
+ * Xavier Claessens <xavier.claessens@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -31,592 +33,395 @@
#include "grl-tracker-source-priv.h"
#include "grl-tracker-utils.h"
-/* --------- Logging -------- */
-
#define GRL_LOG_DOMAIN_DEFAULT tracker_notif_log_domain
GRL_LOG_DOMAIN_STATIC(tracker_notif_log_domain);
-/* ------- Definitions ------- */
-
-#define TRACKER_MEDIA_ITEM \
- "SELECT rdf:type(?urn) tracker:id(?urn) nie:dataSource(?urn) " \
- "WHERE { ?urn a nfo:FileDataObject . " \
- "FILTER (tracker:id(?urn) IN (%s)) }"
+#define GRL_TRACKER_TYPE_SOURCE_NOTIFY grl_tracker_source_notify_get_type ()
+G_DECLARE_FINAL_TYPE (GrlTrackerSourceNotify, grl_tracker_source_notify, GRL_TRACKER, SOURCE_NOTIFY, GObject)
-/**/
+struct _GrlTrackerSourceNotify {
+ GObject parent;
-typedef struct {
- /* tables of items for which we know the source */
- GHashTable *inserted_items;
- GHashTable *deleted_items;
- GHashTable *updated_items;
+ GDBusConnection *conn;
- /* table of items for which we don't know the source */
- GHashTable *orphan_items;
+ /* subject id -> GrlSourceChangeType */
+ GHashTable *updates;
+ /* Number of updates being queried */
+ guint updates_count;
+ /* subject id -> MediaInfo (NULL means it's being queried) */
+ GHashTable *cache;
- /* List of new/old sources */
- GList *new_sources;
- GList *old_sources;
+ guint graph_updated_id;
+ gint rdf_type_id;
+ gint nfo_filedataobject_id;
+};
- /* Convenient stuff (for tracker/own callbacks...) */
- TrackerSparqlCursor *cursor;
- gboolean in_use;
- GrlSourceChangeType change_type;
-} tracker_evt_update_t;
+static void grl_tracker_source_notify_initable_iface_init (GInitableIface *iface);
-/**/
+G_DEFINE_TYPE_WITH_CODE (GrlTrackerSourceNotify, grl_tracker_source_notify, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, grl_tracker_source_notify_initable_iface_init))
-static guint tracker_dbus_signal_id = 0;
+static GrlTrackerSourceNotify *singleton = NULL;
-/**/
-static tracker_evt_update_t *
-tracker_evt_update_new (void)
+typedef struct {
+ gchar *type;
+ gchar *datasource;
+ gchar *url;
+} MediaInfo;
+
+static MediaInfo *
+media_info_new (const gchar *type,
+ const gchar *datasource,
+ const gchar *url)
{
- tracker_evt_update_t *evt = g_slice_new0 (tracker_evt_update_t);
+ MediaInfo *info;
- evt->inserted_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- evt->deleted_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- evt->updated_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ info = g_slice_new (MediaInfo);
+ info->type = g_strdup (type);
+ info->datasource = g_strdup (datasource);
+ info->url = g_strdup (url);
- evt->orphan_items = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- return evt;
+ return info;
}
static void
-tracker_evt_update_free (tracker_evt_update_t *evt)
+media_info_free (MediaInfo *info)
{
- if (!evt)
+ if (info == NULL)
return;
- GRL_DEBUG ("free evt=%p", evt);
-
- g_hash_table_destroy (evt->inserted_items);
- g_hash_table_destroy (evt->deleted_items);
- g_hash_table_destroy (evt->updated_items);
-
- g_hash_table_destroy (evt->orphan_items);
-
- g_list_free (evt->new_sources);
- g_list_free (evt->old_sources);
+ g_free (info->type);
+ g_free (info->datasource);
+ g_free (info->url);
- g_slice_free (tracker_evt_update_t, evt);
+ g_slice_free (MediaInfo, info);
}
static void
-tracker_evt_update_source_add (tracker_evt_update_t *evt,
- const gchar *id,
- const gchar *source_name)
+notify_change (GrlTrackerSourceNotify *self,
+ gint id,
+ GrlSourceChangeType change_type)
{
- GrlTrackerSource *source;
- GrlTrackerSourcePriv *priv;
-
- source = g_hash_table_lookup (grl_tracker_source_sources_modified, id);
- if (!source) {
- source = g_object_new (GRL_TRACKER_SOURCE_TYPE,
- "source-id", id,
- "source-name", source_name,
- "source-desc", GRL_TRACKER_SOURCE_DESC,
- "tracker-connection", grl_tracker_connection,
- "tracker-datasource", id,
- NULL);
- g_hash_table_insert (grl_tracker_source_sources_modified,
- (gpointer) grl_tracker_source_get_tracker_source (source),
- g_object_ref (source));
- } else {
- g_object_ref (source);
- }
+ GrlTrackerSource *source = NULL;
+ gchar *id_str = NULL;
+ GrlMedia *media = NULL;
+ MediaInfo *info;
- priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
- priv->state = GRL_TRACKER_SOURCE_STATE_INSERTING;
- priv->notification_ref++;
+ info = g_hash_table_lookup (self->cache, GINT_TO_POINTER (id));
+ if (info == NULL)
+ goto out;
- evt->new_sources = g_list_append (evt->new_sources, source);
+ if (!grl_tracker_per_device_source)
+ source = grl_tracker_source_find ("");
- GRL_DEBUG ("Preadd source p=%p name=%s id=%s count=%u",
- source, source_name, id, priv->notification_ref);
+ if (!source && info->datasource)
+ source = grl_tracker_source_find (info->datasource);
- g_object_unref (source);
-}
+ if (!source || !GRL_IS_TRACKER_SOURCE (source) ||
+ !grl_tracker_source_can_notify (source))
+ goto out;
-static void
-tracker_evt_update_source_del (tracker_evt_update_t *evt,
- GrlTrackerSource *source)
-{
- GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+ id_str = g_strdup_printf ("%i", id);
+ media = grl_tracker_build_grilo_media (info->type);
+ grl_media_set_id (media, id_str);
+ grl_media_set_url (media, info->url);
- priv->notification_ref++;
- priv->state = GRL_TRACKER_SOURCE_STATE_DELETING;
+ GRL_DEBUG ("Notify: source=%s, change_type=%d, url=%s",
+ grl_source_get_name (GRL_SOURCE (source)),
+ change_type, info->url);
- evt->old_sources = g_list_append (evt->old_sources, source);
+ grl_source_notify_change (GRL_SOURCE (source), media, change_type, FALSE);
- GRL_DEBUG ("Predel source p=%p name=%s id=%s count=%u", source,
- grl_source_get_name (GRL_SOURCE (source)),
- grl_tracker_source_get_tracker_source (source),
- priv->notification_ref);
+out:
+ if (change_type == GRL_CONTENT_REMOVED)
+ g_hash_table_remove (self->cache, GINT_TO_POINTER (id));
+ g_clear_object (&media);
+ g_free (id_str);
}
static void
-tracker_evt_postupdate_sources (tracker_evt_update_t *evt)
+update_query_done (GrlTrackerSourceNotify *self)
{
- GList *source;
+ GHashTableIter iter;
+ gpointer key, value;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
+ /* If more updates came while we were querying, wait for them so we can
+ * aggregate notifications. */
+ self->updates_count--;
+ if (self->updates_count > 0)
+ return;
- source = evt->old_sources;
- while (source != NULL) {
- grl_tracker_del_source (GRL_TRACKER_SOURCE (source->data));
- source = source->next;
- }
+ g_hash_table_iter_init (&iter, self->updates);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ gint id = GPOINTER_TO_INT (key);
+ GrlSourceChangeType change_type = GPOINTER_TO_INT (value);
- source = evt->new_sources;
- while (source != NULL) {
- grl_tracker_add_source (GRL_TRACKER_SOURCE (source->data));
- source = source->next;
+ notify_change (self, id, change_type);
}
- tracker_evt_update_free (evt);
+ g_hash_table_remove_all (self->updates);
}
static void
-tracker_evt_update_orphan_item_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+update_cursor_next_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- guint id;
- const gchar *type, *datasource;
- GrlTrackerSource *source = NULL;
+ GrlTrackerSourceNotify *self = user_data;
+ TrackerSparqlCursor *cursor = (TrackerSparqlCursor *) source_object;
+ const gchar *type;
+ const gchar *datasource;
+ const gchar *url;
+ gint id;
GError *error = NULL;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- if (!tracker_sparql_cursor_next_finish (evt->cursor, result, &error)) {
+ if (!tracker_sparql_cursor_next_finish (cursor, result, &error)) {
if (error != NULL) {
- GRL_DEBUG ("\terror in parsing : %s", error->message);
- g_error_free (error);
- } else {
- GRL_DEBUG ("\tend of parsing...");
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
}
-
- g_clear_object (&evt->cursor);
-
- if (grl_tracker_per_device_source) {
- /* Once all items have been processed, add new sources and we're
- done. */
- tracker_evt_postupdate_sources (evt);
- } else {
- tracker_evt_update_free (evt);
- }
-
+ update_query_done (self);
+ g_object_unref (self);
return;
}
- type = tracker_sparql_cursor_get_string (evt->cursor, 0, NULL);
- id = tracker_sparql_cursor_get_integer (evt->cursor, 1);
- datasource = tracker_sparql_cursor_get_string (evt->cursor, 2, NULL);
+ type = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+ id = tracker_sparql_cursor_get_integer (cursor, 1);
+ datasource = tracker_sparql_cursor_get_string (cursor, 2, NULL);
+ url = tracker_sparql_cursor_get_string (cursor, 3, NULL);
- GRL_DEBUG ("\tOrphan item: id=%u datasource=%s", id, datasource);
+ g_hash_table_insert (self->cache,
+ GINT_TO_POINTER (id),
+ media_info_new (type, datasource, url));
- if (!grl_tracker_per_device_source)
- source = grl_tracker_source_find ("");
-
- if (!source && datasource)
- source = grl_tracker_source_find (datasource);
-
- if (source && GRL_IS_TRACKER_SOURCE (source)) {
- GrlMedia *media;
-
- GRL_DEBUG (" \tAdding to cache id=%u", id);
- grl_tracker_source_cache_add_item (grl_tracker_item_cache, id, source);
-
- if (grl_tracker_source_can_notify (source)) {
- media = grl_tracker_build_grilo_media (type);
- if (media) {
- gchar *str_id = g_strdup_printf ("%i", id);
- gint change_type =
- GPOINTER_TO_INT (g_hash_table_lookup (evt->orphan_items,
- GSIZE_TO_POINTER (id)));
-
- grl_media_set_id (media, str_id);
- g_free (str_id);
-
- GRL_DEBUG ("\tNotify id=%u source=%s p=%p", id,
- grl_source_get_name (GRL_SOURCE (source)),
- source);
- grl_source_notify_change (GRL_SOURCE (source),
- media, change_type, FALSE);
-
- g_object_unref (media);
- }
- }
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphan_item_cb,
- (gpointer) evt);
+ tracker_sparql_cursor_next_async (cursor,
+ NULL,
+ update_cursor_next_cb,
+ self);
}
static void
-tracker_evt_update_orphans_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+update_query_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ GrlTrackerSourceNotify *self = user_data;
+ TrackerSparqlCursor *cursor;
GError *error = NULL;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- evt->cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
- result, &error);
-
- if (error != NULL) {
- GRL_WARNING ("Could not execute sparql query: %s", error->message);
-
- g_error_free (error);
- tracker_evt_postupdate_sources (evt);
+ cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
+ result,
+ &error);
+ if (cursor == NULL) {
+ if (error != NULL) {
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
+ }
+ update_query_done (self);
+ g_object_unref (self);
return;
}
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphan_item_cb,
- (gpointer) evt);
+ tracker_sparql_cursor_next_async (cursor,
+ NULL,
+ update_cursor_next_cb,
+ self);
}
+#define CHANGED GINT_TO_POINTER (GRL_CONTENT_CHANGED)
+#define ADDED GINT_TO_POINTER (GRL_CONTENT_ADDED)
+#define REMOVED GINT_TO_POINTER (GRL_CONTENT_REMOVED)
+
static void
-tracker_evt_update_orphans (tracker_evt_update_t *evt)
+graph_updated_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+
{
- gboolean first = TRUE;
- GString *request_str;
- GHashTableIter iter;
- gpointer key, value;
- GList *source, *sources;
+ GrlTrackerSourceNotify *self = user_data;
+ const gchar *class_name;
+ GVariantIter *iter1, *iter2;
+ gint graph, subject, predicate, object;
+ GString *query;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
+ g_variant_get (parameters, "(&sa(iiii)a(iiii))", &class_name, &iter1, &iter2);
- if (g_hash_table_size (evt->orphan_items) < 1) {
- tracker_evt_postupdate_sources (evt);
- return;
+ GRL_DEBUG ("Tracker update event for class=%s ins=%"G_GSIZE_FORMAT" del=%"G_GSIZE_FORMAT,
+ class_name,
+ g_variant_iter_n_children (iter2),
+ g_variant_iter_n_children (iter1));
+
+ query = g_string_new (NULL);
+
+ /* DELETE */
+ while (g_variant_iter_loop (iter1, "(iiii)", &graph, &subject, &predicate, &object)) {
+ gpointer key = GINT_TO_POINTER (subject);
+
+ /* If a rdf:type is removed, it probably means everything is going to be
+ * removed. The media has been deleted. If some other property is deleted
+ * it means the media already existed but changed.
+ */
+
+ if (predicate == self->rdf_type_id && object == self->nfo_filedataobject_id) {
+ g_hash_table_insert (self->updates, key, REMOVED);
+ } else if (g_hash_table_lookup (self->updates, key) != REMOVED) {
+ g_hash_table_insert (self->updates, key, CHANGED);
+ }
}
- sources = grl_registry_get_sources (grl_registry_get_default (),
- FALSE);
+ /* UPDATE */
+ while (g_variant_iter_loop (iter2, "(iiii)", &graph, &subject, &predicate, &object)) {
+ gpointer key = GINT_TO_POINTER (subject);
- request_str = g_string_new ("");
+ /* If a rdf:type is added it means it's a new media, otherwise it's an
+ * update of an existing media
+ */
- g_hash_table_iter_init (&iter, evt->orphan_items);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- guint id = GPOINTER_TO_UINT (key);
- GrlSourceChangeType change_type = GPOINTER_TO_INT (value);
+ if (predicate == self->rdf_type_id && object == self->nfo_filedataobject_id) {
+ g_hash_table_insert (self->updates, key, ADDED);
+ } else if (g_hash_table_lookup (self->updates, key) != ADDED) {
+ g_hash_table_insert (self->updates, key, CHANGED);
+ }
- if (change_type != GRL_CONTENT_REMOVED) {
- if (first) {
- g_string_append_printf (request_str, "%u", id);
- first = FALSE;
- }
- else {
- g_string_append_printf (request_str, ", %u", id);
- }
- } else {
- /* Notify all sources that a media been removed */
- source = sources;
- while (source != NULL) {
- if (GRL_IS_TRACKER_SOURCE (source->data)) {
- GRL_DEBUG ("\tNotify id=%u source=%s p=%p", id,
- grl_source_get_name (GRL_SOURCE (source->data)),
- source->data);
- if (grl_tracker_source_can_notify (GRL_TRACKER_SOURCE (source->data))) {
- GrlMedia *media = grl_media_new ();
- gchar *str_id = g_strdup_printf ("%u", id);
-
- grl_media_set_id (media, str_id);
- g_free (str_id);
-
- grl_source_notify_change (GRL_SOURCE (source->data),
- media,
- GRL_CONTENT_REMOVED,
- FALSE);
- g_object_unref (media);
- }
- }
- source = source->next;
- }
+ /* If we don't yet have info about this subject query it and add NULL in
+ * the table so we won't query it twice. */
+ if (!g_hash_table_contains (self->cache, key)) {
+ g_string_append_printf (query, "%d,", subject);
+ g_hash_table_insert (self->cache, key, NULL);
}
}
- if (request_str->len > 0) {
- gchar *sparql_final = g_strdup_printf (TRACKER_MEDIA_ITEM, request_str->str);
+ self->updates_count++;
+
+ if (query->len > 0) {
+ /* Remove trailing coma */
+ g_string_truncate (query, query->len - 1);
- GRL_DEBUG ("\trequest : '%s'", sparql_final);
+ g_string_prepend (query,
+ "SELECT rdf:type(?urn) tracker:id(?urn) nie:dataSource(?urn) nie:url(?urn) "
+ "WHERE { ?urn a nfo:FileDataObject . "
+ "FILTER (tracker:id(?urn) IN (");
+ g_string_append (query, "))}");
+ GRL_DEBUG ("Query: %s", query->str);
tracker_sparql_connection_query_async (grl_tracker_connection,
- sparql_final,
+ query->str,
NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphans_cb,
- evt);
-
- g_free (sparql_final);
+ update_query_cb,
+ g_object_ref (self));
} else {
- tracker_evt_postupdate_sources (evt);
+ update_query_done (self);
}
- g_string_free (request_str, TRUE);
+ g_variant_iter_free (iter1);
+ g_variant_iter_free (iter2);
+ g_string_free (query, TRUE);
}
-static void
-tracker_evt_update_items_cb (gpointer key,
- gpointer value,
- tracker_evt_update_t *evt)
+static gboolean
+grl_tracker_source_notify_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
{
- guint id = GPOINTER_TO_INT (key);
- gchar *str_id;
- GrlTrackerSource *source = (GrlTrackerSource *) value;
- GrlMedia *media;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- g_assert (source != NULL);
-
- if (!grl_tracker_source_can_notify (source)) {
- GRL_DEBUG ("\tno notification for source %s...",
- grl_source_get_name (GRL_SOURCE (source)));
- return;
+ GrlTrackerSourceNotify *self = GRL_TRACKER_SOURCE_NOTIFY (initable);
+ TrackerSparqlCursor *cursor;
+
+ self->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
+ if (self->conn == NULL)
+ return FALSE;
+
+ self->graph_updated_id = g_dbus_connection_signal_subscribe (
+ self->conn,
+ TRACKER_DBUS_SERVICE,
+ TRACKER_DBUS_INTERFACE_RESOURCES,
+ "GraphUpdated",
+ TRACKER_DBUS_OBJECT_RESOURCES,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ graph_updated_cb,
+ self, NULL);
+
+ /* Query tracker to know the id of the rdf:type predicate so we can easily
+ * identify them in graph_updated_cb(). */
+ cursor = tracker_sparql_connection_query (grl_tracker_connection,
+ "select tracker:id(rdf:type) tracker:id(nfo:FileDataObject) {}",
+ NULL, error);
+ if (cursor == NULL)
+ return FALSE;
+
+ if (!tracker_sparql_cursor_next (cursor, NULL, error)) {
+ g_object_unref (cursor);
+ return FALSE;
}
- media = grl_media_new ();
- str_id = g_strdup_printf ("%i", id);
- grl_media_set_id (media, str_id);
- g_free (str_id);
+ self->rdf_type_id = tracker_sparql_cursor_get_integer (cursor, 0);
+ self->nfo_filedataobject_id = tracker_sparql_cursor_get_integer (cursor, 1);
- GRL_DEBUG ("\tNotify id=%u source=%s", id,
- grl_source_get_name (GRL_SOURCE (source)));
- grl_source_notify_change (GRL_SOURCE (source), media, evt->change_type, FALSE);
+ g_object_unref (cursor);
- g_object_unref (media);
-}
-
-static void
-tracker_evt_update_items (tracker_evt_update_t *evt)
-{
- evt->change_type = GRL_CONTENT_REMOVED;
- g_hash_table_foreach (evt->deleted_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
- evt->change_type = GRL_CONTENT_ADDED;
- g_hash_table_foreach (evt->inserted_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
- evt->change_type = GRL_CONTENT_CHANGED;
- g_hash_table_foreach (evt->updated_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
+ return TRUE;
}
static void
-tracker_evt_preupdate_sources_item_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+grl_tracker_source_notify_finalize (GObject *object)
{
- const gchar *type, *datasource, *uri, *datasource_name;
- gboolean source_available = FALSE;
- GrlTrackerSource *source;
- GError *error = NULL;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- if (!tracker_sparql_cursor_next_finish (evt->cursor, result, &error)) {
- if (error != NULL) {
- GRL_DEBUG ("\terror in parsing : %s", error->message);
- g_error_free (error);
- } else {
- GRL_DEBUG ("\tend of parsing... start notifying sources");
- }
+ GrlTrackerSourceNotify *self = GRL_TRACKER_SOURCE_NOTIFY (object);
- g_clear_object (&evt->cursor);
+ if (self->conn && self->graph_updated_id)
+ g_dbus_connection_signal_unsubscribe (self->conn, self->graph_updated_id);
- /* Once all sources have been preupdated, start items
- updates. */
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
+ g_clear_object (&self->conn);
+ g_clear_pointer (&self->updates, g_hash_table_unref);
+ g_clear_pointer (&self->cache, g_hash_table_unref);
- return;
- }
-
- type = tracker_sparql_cursor_get_string (evt->cursor, 0, NULL);
- datasource = tracker_sparql_cursor_get_string (evt->cursor, 1, NULL);
- datasource_name = tracker_sparql_cursor_get_string (evt->cursor, 2, NULL);
- uri = tracker_sparql_cursor_get_string (evt->cursor, 3, NULL);
- if (tracker_sparql_cursor_is_bound (evt->cursor, 4))
- source_available = tracker_sparql_cursor_get_boolean (evt->cursor, 4);
-
- source = grl_tracker_source_find (datasource);
-
- GRL_DEBUG ("\tdatasource=%s uri=%s available=%i source=%p",
- datasource, uri, source_available, source);
-
- if (source_available) {
- if (source == NULL) {
- gchar *source_name = grl_tracker_get_source_name (type, uri, datasource,
- datasource_name);
- /* Defer source creation until we have processed all sources */
- if (source_name) {
- tracker_evt_update_source_add (evt, datasource, source_name);
- g_free (source_name);
- }
- } else {
- GRL_DEBUG ("\tChanges on source %p / %s", source, datasource);
- }
- } else if (!source_available && source != NULL) {
- tracker_evt_update_source_del (evt, GRL_TRACKER_SOURCE (source));
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
- (gpointer) evt);
+ G_OBJECT_CLASS (grl_tracker_source_notify_parent_class)->finalize (object);
}
static void
-tracker_evt_preupdate_sources_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+grl_tracker_source_notify_class_init (GrlTrackerSourceNotifyClass *klass)
{
- GError *error = NULL;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- evt->cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
- result, &error);
+ GObjectClass *object_class = (GObjectClass *) klass;
- if (error != NULL) {
- GRL_WARNING ("\tCannot handle datasource request : %s", error->message);
-
- g_error_free (error);
-
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
- return;
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
- (gpointer) evt);
+ GRL_LOG_DOMAIN_INIT (tracker_notif_log_domain, "tracker-notif");
+ object_class->finalize = grl_tracker_source_notify_finalize;
}
static void
-tracker_evt_preupdate_sources (tracker_evt_update_t *evt)
+grl_tracker_source_notify_init (GrlTrackerSourceNotify *self)
{
- tracker_sparql_connection_query_async (grl_tracker_connection,
- TRACKER_DATASOURCES_REQUEST,
- NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_cb,
- evt);
+ self->updates = g_hash_table_new (NULL, NULL);
+ self->cache = g_hash_table_new_full (NULL, NULL,
+ NULL,
+ (GDestroyNotify) media_info_free);
}
static void
-tracker_dbus_signal_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-
+grl_tracker_source_notify_initable_iface_init (GInitableIface *iface)
{
- gchar *class_name;
- gint graph = 0, subject = 0, predicate = 0, object = 0;
- GVariantIter *iter1, *iter2;
- tracker_evt_update_t *evt = tracker_evt_update_new ();
-
- g_variant_get (parameters, "(&sa(iiii)a(iiii))", &class_name, &iter1, &iter2);
-
- GRL_DEBUG ("Tracker update event for class=%s ins=%lu del=%lu evt=%p",
- class_name,
- (unsigned long) g_variant_iter_n_children (iter1),
- (unsigned long) g_variant_iter_n_children (iter2),
- evt);
-
- /* Process deleted items */
- while (g_variant_iter_loop (iter1, "(iiii)", &graph,
- &subject, &predicate, &object)) {
- gpointer psubject = GSIZE_TO_POINTER (subject);
- GrlTrackerSource *source =
- grl_tracker_source_cache_get_source (grl_tracker_item_cache, subject);
-
- /* GRL_DEBUG ("\tdelete=> subject=%i", subject); */
-
- if (source) {
- g_hash_table_insert (evt->deleted_items, psubject,
- g_object_ref (source));
- } else {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_REMOVED));
- }
- }
-
- while (g_variant_iter_loop (iter2, "(iiii)", &graph,
- &subject, &predicate, &object)) {
- gpointer psubject = GSIZE_TO_POINTER (subject);
- GrlTrackerSource *source =
- grl_tracker_source_cache_get_source (grl_tracker_item_cache, subject);
-
- /* GRL_DEBUG ("\tinsert=> subject=%i", subject); */
-
- if (source) {
- /* Removed & inserted items are probably just renamed items... */
- if (g_hash_table_lookup (evt->deleted_items, psubject)) {
- g_hash_table_remove (evt->deleted_items, psubject);
- g_hash_table_insert (evt->updated_items, psubject,
- g_object_ref (source));
- } else if (!g_hash_table_lookup (evt->updated_items, psubject)) {
- g_hash_table_insert (evt->inserted_items, psubject,
- g_object_ref (source));
- }
- } else {
- gpointer state;
-
- if (g_hash_table_lookup_extended (evt->orphan_items, psubject,
- NULL, &state) &&
- (GPOINTER_TO_INT (state) == GRL_CONTENT_REMOVED)) {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_CHANGED));
- } else {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_ADDED));
- }
- }
- }
-
- g_variant_iter_free (iter1);
- g_variant_iter_free (iter2);
-
- GRL_DEBUG ("\tinserted=%i deleted=%i updated=%i orphan=%i",
- g_hash_table_size (evt->inserted_items),
- g_hash_table_size (evt->deleted_items),
- g_hash_table_size (evt->updated_items),
- g_hash_table_size (evt->orphan_items));
-
- if (grl_tracker_per_device_source) {
- tracker_evt_preupdate_sources (evt);
- } else {
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
- }
+ iface->init = grl_tracker_source_notify_initable_init;
}
void
grl_tracker_source_dbus_start_watch (void)
{
- GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-
- tracker_dbus_signal_id = g_dbus_connection_signal_subscribe (connection,
- TRACKER_DBUS_SERVICE,
- TRACKER_DBUS_INTERFACE_RESOURCES,
- "GraphUpdated",
- TRACKER_DBUS_OBJECT_RESOURCES,
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- tracker_dbus_signal_cb,
- NULL,
- NULL);
+ GError *error = NULL;
+
+ if (singleton != NULL)
+ return;
+
+ singleton = g_initable_new (GRL_TRACKER_TYPE_SOURCE_NOTIFY, NULL, &error, NULL);
+ if (singleton == NULL) {
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
+ }
}
void
-grl_tracker_source_init_notifs (void)
+grl_tracker_source_dbus_stop_watch (void)
{
- GRL_LOG_DOMAIN_INIT (tracker_notif_log_domain, "tracker-notif");
+ g_clear_object (&singleton);
}
diff --git a/src/tracker/grl-tracker-source-notif.h b/src/tracker/grl-tracker-source-notif.h
index 8ba3e3d..5646c15 100644
--- a/src/tracker/grl-tracker-source-notif.h
+++ b/src/tracker/grl-tracker-source-notif.h
@@ -50,7 +50,6 @@
/**/
void grl_tracker_source_dbus_start_watch (void);
-
-void grl_tracker_source_init_notifs (void);
+void grl_tracker_source_dbus_stop_watch (void);
#endif /* _GRL_TRACKER_SOURCE_NOTIF_H_ */
diff --git a/src/tracker/grl-tracker.c b/src/tracker/grl-tracker.c
index e3a1a7b..0eee368 100644
--- a/src/tracker/grl-tracker.c
+++ b/src/tracker/grl-tracker.c
@@ -228,7 +228,6 @@ grl_tracker_plugin_init (GrlRegistry *registry,
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- grl_tracker_source_init_notifs ();
grl_tracker_source_init_requests ();
grl_tracker_plugin = plugin;