[PATCH 01/14] tracker: make query requests asynchronous
- From: llandwerlin gmail com
- To: grilo-list gnome org
- Subject: [PATCH 01/14] tracker: make query requests asynchronous
- Date: Mon, 17 Jan 2011 10:17:58 +0000
From: Lionel Landwerlin <lionel g landwerlin linux intel com>
Signed-off-by: Lionel Landwerlin <lionel g landwerlin linux intel com>
---
src/tracker/grl-tracker.c | 390 +++++++++++++++++++++++++++++++++------------
1 files changed, 286 insertions(+), 104 deletions(-)
diff --git a/src/tracker/grl-tracker.c b/src/tracker/grl-tracker.c
index 956341d..5946290 100644
--- a/src/tracker/grl-tracker.c
+++ b/src/tracker/grl-tracker.c
@@ -67,6 +67,34 @@ enum {
SEARCH
};
+/* --- Other --- */
+
+typedef enum {
+ MEDIA_PROP_NONE = 0,
+ MEDIA_PROP_STRING,
+ MEDIA_PROP_INT,
+ MEDIA_PROP_FLOAT,
+} tracker_grl_type_t;
+
+typedef struct {
+ GrlKeyID grl_key;
+ tracker_grl_type_t grl_key_type;
+ const gchar *sparql_key_name;
+ const gchar *sparql_key_attr;
+ const gchar *sparql_key_flavor;
+} tracker_grl_sparql_t;
+
+struct OperationSpec {
+ GrlMediaSource *source;
+ GrlTrackerSourcePriv *priv;
+ guint operation_id;
+ const GList *keys;
+ guint skip;
+ guint count;
+ GrlMediaSourceResultCb callback;
+ gpointer user_data;
+};
+
struct _GrlTrackerSourcePriv {
TrackerSparqlConnection *tracker_connection;
};
@@ -90,6 +118,12 @@ static const GList *grl_tracker_source_supported_keys (GrlMetadataSource *source
static void grl_tracker_source_query (GrlMediaSource *source,
GrlMediaSourceQuerySpec *qs);
+static void setup_key_mappings (void);
+
+/* ===================== Globals ================= */
+
+static GHashTable *grl_to_sparql_mapping = NULL;
+static GHashTable *sparql_to_grl_mapping = NULL;
/* =================== Tracker Plugin =============== */
@@ -162,14 +196,17 @@ grl_tracker_source_class_init (GrlTrackerSourceClass * klass)
GrlMediaSourceClass *source_class = GRL_MEDIA_SOURCE_CLASS (klass);
GrlMetadataSourceClass *metadata_class = GRL_METADATA_SOURCE_CLASS (klass);
GObjectClass *g_class = G_OBJECT_CLASS (klass);
+
source_class->query = grl_tracker_source_query;
- metadata_class->supported_keys = grl_tracker_source_supported_keys;
+ metadata_class->supported_keys = grl_tracker_source_supported_keys;
metadata_class->supported_operations = grl_tracker_source_supported_operations;
g_class->finalize = grl_tracker_source_finalize;
g_type_class_add_private (klass, sizeof (GrlTrackerSourcePriv));
+
+ setup_key_mappings ();
}
static void
@@ -180,6 +217,133 @@ grl_tracker_source_init (GrlTrackerSource *source)
/* ======================= Utilities ==================== */
+static void
+insert_key_mapping (GrlKeyID grl_key,
+ tracker_grl_type_t grl_key_type,
+ const gchar *sparql_key_attr,
+ const gchar *sparql_key_flavor)
+{
+ tracker_grl_sparql_t *assoc = g_slice_new0 (tracker_grl_sparql_t);
+ GList *assoc_list = g_hash_table_lookup (grl_to_sparql_mapping, grl_key);
+ gchar *canon_name = g_strdup (g_param_spec_get_name (grl_key));
+
+ assoc->grl_key = grl_key;
+ assoc->grl_key_type = grl_key_type;
+ assoc->sparql_key_name = g_strdup_printf ("%s_%s",
+ g_strcanon (canon_name,
+ ".-", '_'),
+ sparql_key_flavor);
+ assoc->sparql_key_attr = sparql_key_attr;
+ assoc->sparql_key_flavor = sparql_key_flavor;
+
+ assoc_list = g_list_append (assoc_list, assoc);
+
+ g_hash_table_insert (grl_to_sparql_mapping, grl_key, assoc_list);
+ g_hash_table_insert (sparql_to_grl_mapping,
+ (gpointer) assoc->sparql_key_name,
+ assoc);
+
+ g_free (canon_name);
+}
+
+static void
+setup_key_mappings (void)
+{
+ grl_to_sparql_mapping = g_hash_table_new (g_direct_hash, g_direct_equal);
+ sparql_to_grl_mapping = g_hash_table_new (g_str_hash, g_str_equal);
+
+ insert_key_mapping (GRL_METADATA_KEY_ALBUM,
+ MEDIA_PROP_STRING,
+ "nmm:albumTitle(nmm:musicAlbum(?urn))",
+ "audio");
+
+ insert_key_mapping (GRL_METADATA_KEY_ARTIST,
+ MEDIA_PROP_STRING,
+ "nmm:artistName(nmm:performer(?urn))",
+ "audio");
+
+ insert_key_mapping (GRL_METADATA_KEY_AUTHOR,
+ MEDIA_PROP_STRING,
+ "nmm:artistName(nmm:performer(?urn))",
+ "audio");
+
+ insert_key_mapping (GRL_METADATA_KEY_BITRATE,
+ MEDIA_PROP_NONE,
+ "nfo:averageBitrate(?urn)",
+ "audio");
+
+ insert_key_mapping (GRL_METADATA_KEY_CHILDCOUNT,
+ MEDIA_PROP_STRING,
+ "nfo:entryCounter(?urn)",
+ "directory");
+
+ insert_key_mapping (GRL_METADATA_KEY_DATE,
+ MEDIA_PROP_STRING,
+ "nfo:fileLastModified(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_DURATION,
+ MEDIA_PROP_INT,
+ "nfo:duration(?urn)",
+ "audio");
+
+ insert_key_mapping (GRL_METADATA_KEY_FRAMERATE,
+ MEDIA_PROP_INT,
+ "nfo:frameRate(?urn)",
+ "video");
+
+ insert_key_mapping (GRL_METADATA_KEY_HEIGHT,
+ MEDIA_PROP_NONE,
+ "nfo:height(?urn)",
+ "video");
+
+ insert_key_mapping (GRL_METADATA_KEY_ID,
+ MEDIA_PROP_STRING,
+ "nie:isStoredAs(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_LAST_PLAYED,
+ MEDIA_PROP_STRING,
+ "nfo:fileLastAccessed(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_MIME,
+ MEDIA_PROP_STRING,
+ "nie:mimeType(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_SITE,
+ MEDIA_PROP_STRING,
+ "nie:url(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_TITLE,
+ MEDIA_PROP_STRING,
+ "nie:title(?urn)",
+ "audio");
+ insert_key_mapping (GRL_METADATA_KEY_TITLE,
+ MEDIA_PROP_STRING,
+ "nfo:filename(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_URL,
+ MEDIA_PROP_STRING,
+ "nie:url(?urn)",
+ "file");
+
+ insert_key_mapping (GRL_METADATA_KEY_WIDTH,
+ MEDIA_PROP_NONE,
+ "nfo:width(?urn)",
+ "video");
+}
+
+static tracker_grl_sparql_t *
+get_mapping_from_sparql (const gchar *key)
+{
+ return (tracker_grl_sparql_t *) g_hash_table_lookup (sparql_to_grl_mapping,
+ key);
+}
+
/* Builds an appropriate GrlMedia based on ontology type returned by tracker, or
NULL if unknown */
static GrlMedia *
@@ -219,108 +383,111 @@ build_grilo_media (const gchar *rdf_type)
return media;
}
-/* Execute a sparql query an sends the elements as Grilo medias.
- Returns FALSE if the query failed.
-*/
-static gboolean
-do_tracker_query (GrlMediaSource *source,
- const gchar *sparql_query,
- GrlMediaSourceResultCb callback,
- guint query_id,
- gpointer user_data,
- GError **error)
+static void
+fill_grilo_media_from_sparql (GrlMedia *media,
+ TrackerSparqlCursor *cursor,
+ gint column)
+{
+ const gchar *sparql_key = tracker_sparql_cursor_get_variable_name (cursor, column);
+ tracker_grl_sparql_t *assoc = get_mapping_from_sparql (sparql_key);;
+ union {
+ gint int_val;
+ gdouble double_val;
+ const gchar *str_val;
+ } val;
+
+ GRL_DEBUG ("\tSetting media prop (col=%i/var=%s//prop=%s/type=%i) %s",
+ column,
+ sparql_key,
+ g_param_spec_get_name (G_PARAM_SPEC (assoc->grl_key)),
+ assoc->grl_key_type,
+ tracker_sparql_cursor_get_string (cursor, column, NULL));
+
+ switch (assoc->grl_key_type) {
+ case MEDIA_PROP_STRING:
+ 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);
+ break;
+
+ case MEDIA_PROP_INT:
+ val.int_val = tracker_sparql_cursor_get_integer (cursor, column);
+ grl_data_set_int (GRL_DATA (media), assoc->grl_key, val.int_val);
+ break;
+
+ case MEDIA_PROP_FLOAT:
+ val.double_val = tracker_sparql_cursor_get_double (cursor, column);
+ grl_data_set_float (GRL_DATA (media), assoc->grl_key, (gfloat) val.double_val);
+ break;
+
+ case MEDIA_PROP_NONE:
+ default:
+ grl_data_set_int (GRL_DATA (media), assoc->grl_key, 0);
+ break;
+ }
+}
+
+static void
+tracker_query_cb (GObject *source_object,
+ GAsyncResult *result,
+ struct OperationSpec *operation)
{
- GError *tracker_error = NULL;
- GrlKeyID key;
- GrlMedia *media;
+ gint line, col;
+ const gchar *sparql_type;
+ GError *tracker_error = NULL, *error = NULL;
TrackerSparqlCursor *cursor;
- const gchar *key_name = NULL;
- int i;
- int n_columns;
- int type_column;
-
- cursor =
- tracker_sparql_connection_query (GRL_TRACKER_SOURCE (source)->priv->tracker_connection,
- sparql_query,
- NULL,
- &tracker_error);
- if (!cursor) {
- if (error) {
- *error = g_error_new (GRL_CORE_ERROR,
- GRL_CORE_ERROR_QUERY_FAILED,
- "Query failed: %s",
- tracker_error->message);
- }
- return FALSE;
+ GrlMedia *media;
+
+ GRL_DEBUG ("%s", __FUNCTION__);
+
+ cursor = tracker_sparql_connection_query_finish (operation->priv->tracker_connection,
+ result, &tracker_error);
+
+ if (tracker_error) {
+ GRL_WARNING ("Could not execute sparql query: %s", tracker_error->message);
+
+ error = g_error_new (GRL_CORE_ERROR,
+ GRL_CORE_ERROR_BROWSE_FAILED,
+ "Failed to start browse action : %s",
+ tracker_error->message);
+
+ operation->callback (operation->source, operation->operation_id, NULL, 0,
+ operation->user_data, error);
+
+ g_error_free (tracker_error);
+ g_error_free (error);
+
+ goto end_operation;
}
+ /* Translate Sparql results into Grilo results */
+ line = 0;
while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
- n_columns = tracker_sparql_cursor_get_n_columns (cursor);
- /* Search column with type */
- for (type_column = 0; type_column < n_columns; type_column++) {
- if (strcmp (tracker_sparql_cursor_get_variable_name (cursor,
- type_column),
- MEDIA_TYPE) == 0) {
- break;
- }
- }
-
- /* type not found */
- if (type_column >= n_columns) {
- continue;
- }
-
- media = build_grilo_media (tracker_sparql_cursor_get_string (cursor,
- type_column,
- NULL));
- /* Unknown media */
- if (!media) {
- continue;
- }
-
- /* Fill data */
- for (i = 0; i < n_columns; i++) {
- /* Skip type */
- if (i == type_column) {
- continue;
- }
-
- /* Column has no value */
- if (!tracker_sparql_cursor_is_bound (cursor, i)) {
- continue;
- }
-
- key_name = tracker_sparql_cursor_get_variable_name (cursor, i);
-
- /* Unnamed column */
- if (!key_name) {
- continue;
- }
-
- key = grl_plugin_registry_lookup_metadata_key (grl_plugin_registry_get_default (),
- key_name);
- /* Unknown key */
- if (!key) {
- continue;
- }
-
- grl_data_set_string (GRL_DATA (media),
- key,
- tracker_sparql_cursor_get_string (cursor,
- i,
- NULL));
- }
-
- /* Send data */
- callback (source, query_id, media, -1, user_data, NULL);
- }
+ sparql_type = tracker_sparql_cursor_get_string (cursor, 0, NULL);
- /* Notify there is no more elements */
- callback (source, query_id, NULL, 0, user_data, NULL);
+ GRL_DEBUG ("Parsing line %i of type %s", line, sparql_type);
- g_object_unref (cursor);
+ media = build_grilo_media (sparql_type);
- return TRUE;
+ for (col = 1 ; col < tracker_sparql_cursor_get_n_columns (cursor) ; col++) {
+ fill_grilo_media_from_sparql (media, cursor, col);
+ }
+
+ operation->callback (operation->source,
+ operation->operation_id,
+ media,
+ --operation->count,
+ operation->user_data,
+ NULL);
+
+ line++;
+ }
+
+ end_operation:
+ if (cursor)
+ g_object_unref (G_OBJECT (cursor));
+
+ g_slice_free (struct OperationSpec, operation);
}
/* ================== API Implementation ================ */
@@ -402,7 +569,10 @@ static void
grl_tracker_source_query (GrlMediaSource *source,
GrlMediaSourceQuerySpec *qs)
{
- GError *error = NULL;
+ GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+ GError *error = NULL;
+ struct OperationSpec *os;
+
GRL_DEBUG ("grl_tracker_source_query");
@@ -413,17 +583,29 @@ grl_tracker_source_query (GrlMediaSource *source,
goto send_error;
}
- do_tracker_query (source,
- qs->query,
- qs->callback,
- qs->query_id,
- qs->user_data,
- &error);
-
- if (error) {
+ if (priv->tracker_connection == NULL) {
+ error = g_error_new (GRL_CORE_ERROR,
+ GRL_CORE_ERROR_BROWSE_FAILED,
+ "Failed to start browse action");
goto send_error;
}
+ os = g_slice_new0 (struct OperationSpec);
+ os->source = qs->source;
+ os->priv = priv;
+ os->operation_id = qs->query_id;
+ os->keys = qs->keys;
+ os->skip = qs->skip;
+ os->count = qs->count;
+ os->callback = qs->callback;
+ os->user_data = qs->user_data;
+
+ tracker_sparql_connection_query_async (priv->tracker_connection,
+ qs->query,
+ NULL,
+ (GAsyncReadyCallback) tracker_query_cb,
+ os);
+
return;
send_error:
--
1.7.2.3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]