[PATCH 2/5] tracker: add notification support
- From: lionel g landwerlin linux intel com
- To: grilo-list gnome org
- Subject: [PATCH 2/5] tracker: add notification support
- Date: Tue, 8 Feb 2011 19:49:30 +0000
From: Lionel Landwerlin <lionel g landwerlin linux intel com>
Signed-off-by: Lionel Landwerlin <lionel g landwerlin linux intel com>
---
src/tracker/Makefile.am | 4 +-
src/tracker/grl-tracker-utils.c | 73 ++++++
src/tracker/grl-tracker-utils.h | 19 ++
src/tracker/grl-tracker.c | 530 +++++++++++++++++++++++++++++++--------
4 files changed, 516 insertions(+), 110 deletions(-)
create mode 100644 src/tracker/grl-tracker-utils.c
create mode 100644 src/tracker/grl-tracker-utils.h
diff --git a/src/tracker/Makefile.am b/src/tracker/Makefile.am
index 5510f5a..7e407cb 100644
--- a/src/tracker/Makefile.am
+++ b/src/tracker/Makefile.am
@@ -21,7 +21,9 @@ libgrltracker_la_LDFLAGS = \
libgrltracker_la_SOURCES = \
grl-tracker.c \
- grl-tracker.h
+ grl-tracker.h \
+ grl-tracker-utils.c \
+ grl-tracker-utils.h
libdir = $(GRL_PLUGINS_DIR)
trackerxmldir = $(GRL_PLUGINS_CONF_DIR)
diff --git a/src/tracker/grl-tracker-utils.c b/src/tracker/grl-tracker-utils.c
new file mode 100644
index 0000000..79829dd
--- /dev/null
+++ b/src/tracker/grl-tracker-utils.c
@@ -0,0 +1,73 @@
+#include <glib.h>
+
+#include "grl-tracker-utils.h"
+
+/* TODO: is it worth to have an LRU ? */
+struct _GrlTrackerItemCache {
+ gsize size_limit;
+ gsize size_current;
+
+ GHashTable *table;
+ GList *list;
+};
+
+GrlTrackerItemCache *
+grl_tracker_item_cache_new (gsize size)
+{
+ GrlTrackerItemCache *cache;
+
+ g_return_val_if_fail (size > 0, NULL);
+
+ cache = g_slice_new0 (GrlTrackerItemCache);
+
+ if (!cache)
+ return NULL;
+
+ cache->size_limit = size;
+ cache->table = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ return cache;
+}
+
+void
+grl_tracker_item_cache_free (GrlTrackerItemCache *cache)
+{
+ g_return_if_fail (cache != NULL);
+
+ g_list_free (cache->list);
+ g_hash_table_destroy (cache->table);
+
+ g_slice_free (GrlTrackerItemCache, cache);
+}
+
+void
+grl_tracker_item_cache_add_item (GrlTrackerItemCache *cache,
+ guint id,
+ GrlTrackerSource *source)
+{
+ GList *last;
+
+ g_return_if_fail (cache != NULL);
+
+ if (g_hash_table_lookup (cache->table, GSIZE_TO_POINTER (id)) != NULL)
+ return;
+
+ if (cache->size_current >= cache->size_limit) {
+ last = g_list_last (cache->list); /* TODO: optimize that ! */
+ g_hash_table_remove (cache->table, last->data);
+ cache->list = g_list_remove_link (cache->list, last);
+ }
+
+ cache->list = g_list_prepend (cache->list, GSIZE_TO_POINTER (id));
+ g_hash_table_insert (cache->table, GSIZE_TO_POINTER (id), source);
+ cache->size_current++;
+}
+
+GrlTrackerSource *
+grl_tracker_item_cache_get_source (GrlTrackerItemCache *cache, guint id)
+{
+ g_return_val_if_fail (cache != NULL, NULL);
+
+ return (GrlTrackerSource *) g_hash_table_lookup (cache->table,
+ GSIZE_TO_POINTER (id));
+}
diff --git a/src/tracker/grl-tracker-utils.h b/src/tracker/grl-tracker-utils.h
new file mode 100644
index 0000000..be82e0d
--- /dev/null
+++ b/src/tracker/grl-tracker-utils.h
@@ -0,0 +1,19 @@
+#ifndef _GRL_TRACKER_UTILS_H_
+#define _GRL_TRACKER_UTILS_H_
+
+#include "grl-tracker.h"
+
+typedef struct _GrlTrackerItemCache GrlTrackerItemCache;
+
+GrlTrackerItemCache *grl_tracker_item_cache_new (gsize size);
+
+void grl_tracker_item_cache_free (GrlTrackerItemCache *cache);
+
+void grl_tracker_item_cache_add_item (GrlTrackerItemCache *cache,
+ guint id,
+ GrlTrackerSource *source);
+
+GrlTrackerSource *grl_tracker_item_cache_get_source (GrlTrackerItemCache *cache,
+ guint id);
+
+#endif /* _GRL_TRACKER_UTILS_H_ */
diff --git a/src/tracker/grl-tracker.c b/src/tracker/grl-tracker.c
index 4a9dfef..2ac5254 100644
--- a/src/tracker/grl-tracker.c
+++ b/src/tracker/grl-tracker.c
@@ -33,6 +33,7 @@
#include <tracker-sparql.h>
#include "grl-tracker.h"
+#include "grl-tracker-utils.h"
/* --------- Logging -------- */
@@ -51,6 +52,8 @@ GRL_LOG_DOMAIN_STATIC(tracker_log_domain);
#define RDF_TYPE_VIDEO "nmm#Video"
#define RDF_TYPE_BOX "grilo#Box"
+#define TRACKER_ITEM_CACHE_SIZE (10000)
+
/* ---- Plugin information --- */
#define PLUGIN_ID TRACKER_PLUGIN_ID
@@ -82,6 +85,13 @@ enum {
#define TRACKER_MOUNTED_DATASOURCES_END " ))} GROUP BY (?datasource)"
+#define TRACKER_SOURCE_ITEM_START \
+ "SELECT rdf:type(?urn) tracker:id(?urn) nie:dataSource(?urn) " \
+ "WHERE { ?urn a nfo:FileDataObject . " \
+ "FILTER (tracker:id(?urn) IN ("
+
+#define TRACKER_SOURCE_ITEM_END ")) }"
+
#define TRACKER_DATASOURCES_REQUEST \
"SELECT ?urn nie:dataSource(?urn) AS ?source " \
"(SELECT GROUP_CONCAT(nie:url(tracker:mountPoint(?ds)), \",\") " \
@@ -137,15 +147,27 @@ typedef struct {
} tracker_grl_sparql_t;
typedef struct {
- gboolean in_use;
-
+ /* tables of items we know the source */
+ GHashTable *inserted_items;
+ GHashTable *deleted_items;
GHashTable *updated_items;
- GList *updated_items_list;
- GList *updated_items_iter;
- /* GList *updated_sources; */
+ /* table of items we don't know the source */
+ GHashTable *orphan_items;
- TrackerSparqlCursor *cursor;
+ /* Global list of all impacted items, used to figure out which
+ sources have been added/removed. */
+ GHashTable *altered_items;
+ GList *altered_items_list;
+ GList *altered_items_iter;
+
+ /* List of new sources */
+ GList *new_sources;
+
+ /* Convenient stuff (for tracker/own callbacks...) */
+ TrackerSparqlCursor *cursor;
+ gboolean in_use;
+ GrlMediaSourceChangeType change_type;
} tracker_evt_update_t;
struct OperationSpec {
@@ -173,6 +195,7 @@ struct _GrlTrackerSourcePriv {
GHashTable *operations;
gchar *tracker_datasource;
+ gboolean notify_changes;
};
#define GRL_TRACKER_SOURCE_GET_PRIVATE(object) \
@@ -212,6 +235,12 @@ static void grl_tracker_source_browse (GrlMediaSource *source,
static void grl_tracker_source_cancel (GrlMediaSource *source,
guint operation_id);
+static gboolean grl_tracker_source_change_start (GrlMediaSource *source,
+ GError **error);
+
+static gboolean grl_tracker_source_change_stop (GrlMediaSource *source,
+ GError **error);
+
static gchar *get_tracker_source_name (const gchar *uri,
const gchar *datasource);
@@ -227,16 +256,79 @@ static TrackerSparqlConnection *tracker_connection = NULL;
static gboolean tracker_per_device_source = FALSE;
static const GrlPluginInfo *tracker_grl_plugin;
static guint tracker_dbus_signal_id = 0;
+static GrlTrackerItemCache *tracker_item_cache;
/* =================== Tracker Plugin =============== */
+static void
+grl_tracker_add_source (GrlTrackerSource *source)
+{
+ grl_plugin_registry_register_source (grl_plugin_registry_get_default (),
+ tracker_grl_plugin,
+ GRL_MEDIA_PLUGIN (source),
+ NULL);
+}
+
+static void
+grl_tracker_del_source (GrlTrackerSource *source)
+{
+ grl_plugin_registry_unregister_source (grl_plugin_registry_get_default (),
+ GRL_MEDIA_PLUGIN (source),
+ NULL);
+}
+
+/* Builds an appropriate GrlMedia based on ontology type returned by
+ tracker, or NULL if unknown */
+static GrlMedia *
+build_grilo_media (const gchar *rdf_type)
+{
+ GrlMedia *media = NULL;
+ gchar **rdf_single_type;
+ int i;
+
+ if (!rdf_type) {
+ return NULL;
+ }
+
+ /* As rdf_type can be formed by several types, split them */
+ rdf_single_type = g_strsplit (rdf_type, ",", -1);
+ i = g_strv_length (rdf_single_type) - 1;
+
+ while (!media && i >= 0) {
+ if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_MUSIC)) {
+ media = grl_media_audio_new ();
+ } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_VIDEO)) {
+ media = grl_media_video_new ();
+ } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_IMAGE)) {
+ media = grl_media_image_new ();
+ } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_ARTIST)) {
+ media = grl_media_box_new ();
+ } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_ALBUM)) {
+ media = grl_media_box_new ();
+ } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_BOX)) {
+ media = grl_media_box_new ();
+ }
+ i--;
+ }
+
+ g_strfreev (rdf_single_type);
+
+ return media;
+}
+
static tracker_evt_update_t *
tracker_evt_update_new (void)
{
tracker_evt_update_t *evt = g_slice_new0 (tracker_evt_update_t);
+ evt->altered_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ evt->inserted_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+ evt->deleted_items = g_hash_table_new (g_direct_hash, g_direct_equal);
evt->updated_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+ evt->orphan_items = g_hash_table_new (g_direct_hash, g_direct_equal);
+
return evt;
}
@@ -246,8 +338,16 @@ tracker_evt_update_free (tracker_evt_update_t *evt)
if (!evt)
return;
+ g_hash_table_destroy (evt->altered_items);
+ g_list_free (evt->altered_items_list);
+
+ g_hash_table_destroy (evt->inserted_items);
+ g_hash_table_destroy (evt->deleted_items);
g_hash_table_destroy (evt->updated_items);
- g_list_free (evt->updated_items_list);
+
+ g_hash_table_destroy (evt->orphan_items);
+
+ g_list_free (evt->new_sources);
if (evt->cursor != NULL)
g_object_unref (evt->cursor);
@@ -256,26 +356,193 @@ tracker_evt_update_free (tracker_evt_update_t *evt)
}
static void
-grl_tracker_add_source (GrlTrackerSource *source)
+tracker_evt_postupdate_sources (tracker_evt_update_t *evt)
{
- grl_plugin_registry_register_source (grl_plugin_registry_get_default (),
- tracker_grl_plugin,
- GRL_MEDIA_PLUGIN (source),
- NULL);
+ GList *new_source = evt->new_sources;
+
+ while (new_source != NULL) {
+ grl_tracker_add_source (GRL_TRACKER_SOURCE (new_source->data));
+ new_source = new_source->next;
+ }
+
+ tracker_evt_update_free (evt);
}
static void
-grl_tracker_del_source (GrlTrackerSource *source)
+tracker_evt_update_orphan_item_cb (GObject *object,
+ GAsyncResult *result,
+ tracker_evt_update_t *evt)
{
- grl_plugin_registry_unregister_source (grl_plugin_registry_get_default (),
- GRL_MEDIA_PLUGIN (source),
- NULL);
+ guint id;
+ const gchar *datasource;
+ GrlMediaPlugin *plugin;
+ GError *tracker_error = NULL;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ if (!tracker_sparql_cursor_next_finish (evt->cursor,
+ result,
+ &tracker_error)) {
+ if (tracker_error != NULL) {
+ GRL_DEBUG ("\terror in parsing : %s", tracker_error->message);
+ g_error_free (tracker_error);
+ } else {
+ GRL_DEBUG ("\tend of parsing...");
+ }
+
+ /* Once all items have been processed, add new sources and we're
+ done. */
+ tracker_evt_postupdate_sources (evt);
+
+ return;
+ }
+
+ id = tracker_sparql_cursor_get_integer (evt->cursor, 1);
+ datasource = tracker_sparql_cursor_get_string (evt->cursor, 2, NULL);
+
+ plugin = grl_plugin_registry_lookup_source (grl_plugin_registry_get_default (),
+ datasource);
+
+ if (plugin) {
+ GrlMedia *media =
+ build_grilo_media (tracker_sparql_cursor_get_string (evt->cursor, 0, NULL));
+ 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_data_set_string (GRL_DATA (media), GRL_METADATA_KEY_ID, str_id);
+
+ GRL_DEBUG ("Update op=%i item=%i", change_type, id);
+
+ grl_media_source_notify_change (GRL_MEDIA_SOURCE (plugin), media,
+ change_type, FALSE);
+
+ g_free (str_id);
+ }
+}
+
+static void
+tracker_evt_update_orphans_cb (GObject *object,
+ GAsyncResult *result,
+ tracker_evt_update_t *evt)
+{
+ GError *tracker_error = NULL;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ if (evt->cursor != NULL)
+ g_object_unref (evt->cursor);
+ evt->cursor = tracker_sparql_connection_query_finish (tracker_connection,
+ result, NULL);
+
+ if (tracker_error != NULL) {
+ GRL_WARNING ("Could not execute sparql query: %s", tracker_error->message);
+
+ g_error_free (tracker_error);
+ tracker_evt_update_free (evt); /* TODO: change order with
+ sources/items parsing */
+ return;
+ }
+
+ tracker_sparql_cursor_next_async (evt->cursor, NULL,
+ (GAsyncReadyCallback) tracker_evt_update_orphan_item_cb,
+ (gpointer) evt);
+}
+
+static void
+tracker_evt_update_orphans (tracker_evt_update_t *evt)
+{
+ GString *request_str;
+ GList *subject, *subjects;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ if (g_hash_table_size (evt->orphan_items) < 1)
+ return;
+
+ request_str = g_string_new (TRACKER_SOURCE_ITEM_START);
+ subjects = g_hash_table_get_keys (evt->orphan_items);
+ subject = subjects;
+
+ g_string_append_printf (request_str, "%i", GPOINTER_TO_INT (subject->data));
+ subject = subject->next;
+
+ while (subject != NULL) {
+ g_string_append_printf (request_str, ", %i",
+ GPOINTER_TO_INT (subject->data));
+ subject = subject->next;
+ }
+ g_list_free (subjects);
+
+ g_string_append (request_str, TRACKER_SOURCE_ITEM_END);
+
+ GRL_DEBUG ("\trequest : '%s'", request_str->str);
+
+ tracker_sparql_connection_query_async (tracker_connection, request_str->str,
+ NULL, (GAsyncReadyCallback) tracker_evt_update_orphans_cb,
+ evt);
+
+ g_string_free (request_str, TRUE);
+}
+
+static void
+tracker_evt_update_items_cb (gpointer key,
+ gpointer value,
+ tracker_evt_update_t *evt)
+{
+ guint id = GPOINTER_TO_INT (key);
+ gchar *str_id;
+ GrlTrackerSource *source = (GrlTrackerSource *) value;
+ GrlTrackerSourcePriv *priv;
+ GrlMedia *media;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ if (!source) {
+ g_assert ("not in cache ???");
+ return;
+ }
+
+ priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+
+ if (!priv->notify_changes) {
+ GRL_DEBUG ("no notification for source %s...",
+ grl_metadata_source_get_name (GRL_METADATA_SOURCE (source)));
+ return;
+ }
+
+ media = grl_media_new ();
+ str_id = g_strdup_printf ("%i", id);
+ grl_data_set_string (GRL_DATA (media), GRL_METADATA_KEY_ID, str_id);
+
+ GRL_DEBUG ("Update op=%i item=%i on source %s", evt->change_type, id,
+ grl_metadata_source_get_name (GRL_METADATA_SOURCE (source)));
+
+ grl_media_source_notify_change (GRL_MEDIA_SOURCE (source), media,
+ evt->change_type, FALSE);
+
+ g_free (str_id);
}
static void
-tracker_evt_update_process_item_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+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);
+}
+
+static void
+tracker_evt_preupdate_sources_item_cb (GObject *object,
+ GAsyncResult *result,
+ tracker_evt_update_t *evt)
{
const gchar *datasource, *uri;
gboolean source_mounted;
@@ -292,10 +559,14 @@ tracker_evt_update_process_item_cb (GObject *object,
GRL_DEBUG ("\terror in parsing : %s", tracker_error->message);
g_error_free (tracker_error);
} else {
- GRL_DEBUG ("\tend of parsing :)");
+ GRL_DEBUG ("\tend of parsing... start notifying sources");
}
- tracker_evt_update_free (evt);
+ /* Once all sources have been preupdated, start items
+ updates. */
+ tracker_evt_update_items (evt);
+ tracker_evt_update_orphans (evt);
+
return;
}
@@ -319,7 +590,8 @@ tracker_evt_update_process_item_cb (GObject *object,
"source-desc", SOURCE_DESC,
"tracker-connection", tracker_connection,
NULL);
- grl_tracker_add_source (GRL_TRACKER_SOURCE (plugin));
+ /* Defer source creation until we have processed all sources */
+ evt->new_sources = g_list_append (evt->new_sources, plugin);
g_free (source_name);
} else {
GRL_DEBUG ("\tChanges on source %p / %s", plugin, datasource);
@@ -329,19 +601,21 @@ tracker_evt_update_process_item_cb (GObject *object,
}
tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_process_item_cb,
+ (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
(gpointer) evt);
}
static void
-tracker_evt_update_process_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+tracker_evt_preupdate_sources_cb (GObject *object,
+ GAsyncResult *result,
+ tracker_evt_update_t *evt)
{
GError *tracker_error = NULL;
GRL_DEBUG ("%s", __FUNCTION__);
+ if (evt->cursor != NULL)
+ g_object_unref (evt->cursor);
evt->cursor = tracker_sparql_connection_query_finish (tracker_connection,
result, NULL);
@@ -354,37 +628,38 @@ tracker_evt_update_process_cb (GObject *object,
}
tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_process_item_cb,
+ (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
(gpointer) evt);
}
static void
-tracker_evt_update_process (tracker_evt_update_t *evt)
+tracker_evt_preupdate_sources (tracker_evt_update_t *evt)
{
GString *request_str = g_string_new (TRACKER_MOUNTED_DATASOURCES_START);
GRL_DEBUG ("%s", __FUNCTION__);
- evt->updated_items_iter = evt->updated_items_list;
+ evt->altered_items_iter = evt->altered_items_list;
g_string_append_printf (request_str, "%i",
- GPOINTER_TO_INT (evt->updated_items_iter->data));
- evt->updated_items_iter = evt->updated_items_iter->next;
+ GPOINTER_TO_INT (evt->altered_items_iter->data));
+ evt->altered_items_iter = evt->altered_items_iter->next;
- while (evt->updated_items_iter != NULL) {
+ while (evt->altered_items_iter != NULL) {
g_string_append_printf (request_str, ", %i",
- GPOINTER_TO_INT (evt->updated_items_iter->data));
- evt->updated_items_iter = evt->updated_items_iter->next;
+ GPOINTER_TO_INT (evt->altered_items_iter->data));
+ evt->altered_items_iter = evt->altered_items_iter->next;
}
g_string_append (request_str, TRACKER_MOUNTED_DATASOURCES_END);
- GRL_DEBUG ("\trequest : %s", request_str->str);
+ GRL_DEBUG ("\trequest : '%s'", request_str->str);
tracker_sparql_connection_query_async (tracker_connection,
request_str->str,
NULL,
- (GAsyncReadyCallback) tracker_evt_update_process_cb,
+ (GAsyncReadyCallback) tracker_evt_preupdate_sources_cb,
evt);
+
g_string_free (request_str, TRUE);
}
@@ -412,48 +687,95 @@ tracker_dbus_signal_cb (GDBusConnection *connection,
(unsigned long) g_variant_iter_n_children (iter1),
(unsigned long) g_variant_iter_n_children (iter2));
+ /* Process deleted items */
while (g_variant_iter_loop (iter1, "(iiii)", &graph,
&subject, &predicate, &object)) {
- subject_state = GPOINTER_TO_INT (g_hash_table_lookup (evt->updated_items,
- GSIZE_TO_POINTER (subject)));
+ gpointer psubject = GSIZE_TO_POINTER (subject);
+ GrlTrackerSource *source = grl_tracker_item_cache_get_source (tracker_item_cache,
+ subject);
+
+ GRL_DEBUG ("delete=> subject=%i", subject);
+
+ if (source) {
+ g_hash_table_insert (evt->deleted_items, psubject, source);
+ } else {
+ g_hash_table_insert (evt->orphan_items, psubject,
+ GSIZE_TO_POINTER (GRL_CONTENT_REMOVED));
+ }
+
+ subject_state = GPOINTER_TO_INT (g_hash_table_lookup (evt->altered_items,
+ psubject));
if (subject_state == 0) {
- g_hash_table_insert (evt->updated_items,
- GSIZE_TO_POINTER (subject),
- GSIZE_TO_POINTER (1));
- evt->updated_items_list = g_list_append (evt->updated_items_list,
- GSIZE_TO_POINTER (subject));
- } else if (subject_state == 2)
- evt->updated_items_list = g_list_append (evt->updated_items_list,
- GSIZE_TO_POINTER (subject));
+
+ g_hash_table_insert (evt->altered_items, psubject, GSIZE_TO_POINTER (1));
+ evt->altered_items_list = g_list_append (evt->altered_items_list,
+ psubject);
+ } else if (subject_state == 2) {
+ evt->altered_items_list = g_list_append (evt->altered_items_list,
+ psubject);
+ }
}
g_variant_iter_free (iter1);
-
+ /* Process inserted items */
while (g_variant_iter_loop (iter2, "(iiii)", &graph,
&subject, &predicate, &object)) {
- subject_state = GPOINTER_TO_INT (g_hash_table_lookup (evt->updated_items,
+ gpointer psubject = GSIZE_TO_POINTER (subject);
+ GrlTrackerSource *source = grl_tracker_item_cache_get_source (tracker_item_cache,
+ subject);
+
+ GRL_DEBUG ("insert=> 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, source);
+ } else if (!g_hash_table_lookup (evt->updated_items, psubject)) {
+ g_hash_table_insert (evt->inserted_items, psubject, 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));
+ }
+ }
+
+ subject_state = GPOINTER_TO_INT (g_hash_table_lookup (evt->altered_items,
GSIZE_TO_POINTER (subject)));
if (subject_state == 0) {
- g_hash_table_insert (evt->updated_items,
+ g_hash_table_insert (evt->altered_items,
GSIZE_TO_POINTER (subject),
GSIZE_TO_POINTER (1));
- evt->updated_items_list = g_list_append (evt->updated_items_list,
- GSIZE_TO_POINTER (subject));
+ evt->altered_items_list = g_list_append (evt->altered_items_list,
+ GSIZE_TO_POINTER (subject));
} else if (subject_state == 2)
- evt->updated_items_list = g_list_append (evt->updated_items_list,
- GSIZE_TO_POINTER (subject));
+ evt->altered_items_list = g_list_append (evt->altered_items_list,
+ GSIZE_TO_POINTER (subject));
}
g_variant_iter_free (iter2);
- evt->updated_items_iter = evt->updated_items_list;
+ evt->altered_items_iter = evt->altered_items_list;
- GRL_DEBUG ("\t%u elements updated", g_hash_table_size (evt->updated_items));
+ GRL_DEBUG ("\tinserted=%i deleted=%i updated=%i orphan=%i changed=%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),
+ g_hash_table_size (evt->altered_items));
GRL_DEBUG ("\t%u elements updated (list)",
- g_list_length (evt->updated_items_list));
+ g_list_length (evt->altered_items_list));
- tracker_evt_update_process (evt);
+ tracker_evt_preupdate_sources (evt);
}
static void
@@ -512,10 +834,7 @@ tracker_get_datasource_cb (GObject *object,
"source-desc", SOURCE_DESC,
"tracker-connection", tracker_connection,
NULL);
- grl_plugin_registry_register_source (grl_plugin_registry_get_default (),
- tracker_grl_plugin,
- GRL_MEDIA_PLUGIN (source),
- NULL);
+ grl_tracker_add_source (source);
g_free (source_name);
}
@@ -586,6 +905,7 @@ grl_tracker_plugin_init (GrlPluginRegistry *registry,
GRL_DEBUG ("%s", __FUNCTION__);
tracker_grl_plugin = plugin;
+ tracker_item_cache = grl_tracker_item_cache_new (TRACKER_ITEM_CACHE_SIZE);
if (!configs) {
GRL_WARNING ("Configuration not provided! Using default configuration.");
@@ -635,11 +955,13 @@ grl_tracker_source_class_init (GrlTrackerSourceClass * klass)
GrlMetadataSourceClass *metadata_class = GRL_METADATA_SOURCE_CLASS (klass);
GObjectClass *g_class = G_OBJECT_CLASS (klass);
- source_class->query = grl_tracker_source_query;
- source_class->metadata = grl_tracker_source_metadata;
- source_class->search = grl_tracker_source_search;
- source_class->browse = grl_tracker_source_browse;
- source_class->cancel = grl_tracker_source_cancel;
+ source_class->query = grl_tracker_source_query;
+ source_class->metadata = grl_tracker_source_metadata;
+ source_class->search = grl_tracker_source_search;
+ source_class->browse = grl_tracker_source_browse;
+ source_class->cancel = grl_tracker_source_cancel;
+ source_class->notify_change_start = grl_tracker_source_change_start;
+ source_class->notify_change_stop = grl_tracker_source_change_stop;
metadata_class->supported_keys = grl_tracker_source_supported_keys;
@@ -942,47 +1264,9 @@ get_select_string (GrlMediaSource *source, const GList *keys)
return g_string_free (gstr, FALSE);
}
-/* Builds an appropriate GrlMedia based on ontology type returned by tracker, or
- NULL if unknown */
-static GrlMedia *
-build_grilo_media (const gchar *rdf_type)
-{
- GrlMedia *media = NULL;
- gchar **rdf_single_type;
- int i;
-
- if (!rdf_type) {
- return NULL;
- }
-
- /* As rdf_type can be formed by several types, split them */
- rdf_single_type = g_strsplit (rdf_type, ",", -1);
- i = g_strv_length (rdf_single_type) - 1;
-
- while (!media && i >= 0) {
- if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_MUSIC)) {
- media = grl_media_audio_new ();
- } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_VIDEO)) {
- media = grl_media_video_new ();
- } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_IMAGE)) {
- media = grl_media_image_new ();
- } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_ARTIST)) {
- media = grl_media_box_new ();
- } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_ALBUM)) {
- media = grl_media_box_new ();
- } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_BOX)) {
- media = grl_media_box_new ();
- }
- i--;
- }
-
- g_strfreev (rdf_single_type);
-
- return media;
-}
-
static void
-fill_grilo_media_from_sparql (GrlMedia *media,
+fill_grilo_media_from_sparql (GrlTrackerSource *source,
+ GrlMedia *media,
TrackerSparqlCursor *cursor,
gint column)
{
@@ -1015,6 +1299,12 @@ fill_grilo_media_from_sparql (GrlMedia *media,
switch (G_PARAM_SPEC (assoc->grl_key)->value_type) {
case G_TYPE_STRING:
+ /* Cache the source associated to this result. */
+ if (assoc->grl_key == GRL_METADATA_KEY_ID) {
+ grl_tracker_item_cache_add_item (tracker_item_cache,
+ tracker_sparql_cursor_get_integer (cursor, column),
+ source);
+ }
val.str_val = tracker_sparql_cursor_get_string (cursor, column, NULL);
if (val.str_val != NULL)
grl_data_set_string (GRL_DATA (media), assoc->grl_key, val.str_val);
@@ -1102,7 +1392,8 @@ tracker_query_result_cb (GObject *source_object,
for (col = 1 ;
col < tracker_sparql_cursor_get_n_columns (operation->cursor) ;
col++) {
- fill_grilo_media_from_sparql (media, operation->cursor, col);
+ fill_grilo_media_from_sparql (GRL_TRACKER_SOURCE (operation->source),
+ media, operation->cursor, col);
}
operation->callback (operation->source,
@@ -1197,7 +1488,8 @@ tracker_metadata_cb (GObject *source_object,
/* Translate Sparql result into Grilo result */
for (col = 0 ; col < tracker_sparql_cursor_get_n_columns (cursor) ; col++) {
- fill_grilo_media_from_sparql (ms->media, cursor, col);
+ fill_grilo_media_from_sparql (GRL_TRACKER_SOURCE (ms->source),
+ ms->media, cursor, col);
}
ms->callback (ms->source, ms->media, ms->user_data, NULL);
@@ -1333,7 +1625,7 @@ grl_tracker_source_query (GrlMediaSource *source,
return;
}
- GRL_DEBUG ("select : %s", qs->query);
+ GRL_DEBUG ("select : '%s'", qs->query);
os = tracker_operation_initiate (source, priv, qs->query_id);
os->keys = qs->keys;
@@ -1505,3 +1797,23 @@ grl_tracker_source_cancel (GrlMediaSource *source, guint operation_id)
if (os != NULL)
g_cancellable_cancel (os->cancel_op);
}
+
+static gboolean
+grl_tracker_source_change_start (GrlMediaSource *source, GError **error)
+{
+ GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+
+ priv->notify_changes = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
+grl_tracker_source_change_stop (GrlMediaSource *source, GError **error)
+{
+ GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+
+ priv->notify_changes = FALSE;
+
+ return TRUE;
+}
--
1.7.2.3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]