[PATCH 01/14] tracker: make query requests asynchronous



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]