[PATCH 07/14] tracker: add browsing support



From: Lionel Landwerlin <lionel g landwerlin linux intel com>

Support flat & directory browsing

Signed-off-by: Lionel Landwerlin <lionel g landwerlin linux intel com>
---
 src/tracker/grl-tracker.c |  287 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 269 insertions(+), 18 deletions(-)

diff --git a/src/tracker/grl-tracker.c b/src/tracker/grl-tracker.c
index c028f20..eed2e05 100644
--- a/src/tracker/grl-tracker.c
+++ b/src/tracker/grl-tracker.c
@@ -4,6 +4,7 @@
  * Contact: Iago Toral Quiroga <itoral igalia com>
  *
  * Authors: Juan A. Suarez Romero <jasuarez igalia com>
+ *          Lionel Landwerlin <lionel g landwerlin linux intel com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -46,6 +47,7 @@ GRL_LOG_DOMAIN_STATIC(tracker_log_domain);
 #define RDF_TYPE_AUDIO  "nmm#MusicPiece"
 #define RDF_TYPE_IMAGE  "nmm#Photo"
 #define RDF_TYPE_VIDEO  "nmm#Video"
+#define RDF_TYPE_FOLDER "nfo#Folder"
 #define RDF_TYPE_BOX    "grilo#Box"
 
 /* ---- Plugin information --- */
@@ -69,6 +71,41 @@ enum {
 
 /* --- Other --- */
 
+#define TRACKER_BROWSE_FLAT_REQUEST "                               \
+  SELECT %s                                                         \
+  WHERE {                                                           \
+    { ?urn a nmm:Video } UNION                                      \
+    { ?urn a nmm:Photo } UNION                                      \
+    { ?urn a nmm:MusicPiece } .                                     \
+    ?urn tracker:available ?tr .                                    \
+  }                                                                 \
+  ORDER BY DESC(nfo:fileLastModified(?urn))                         \
+  OFFSET %i LIMIT %i"
+
+#define TRACKER_BROWSE_DIRECTORY_ROOT_REQUEST "                       \
+  SELECT %s nie:isPartOf(?urn) AS ?parent                             \
+  WHERE {                                                             \
+    ?urn a nfo:Folder .                                               \
+    ?urn tracker:available ?tr .                                      \
+    OPTIONAL { ?urn nie:isPartOf ?parent }                            \
+    FILTER (! bound(?parent))                                         \
+    }                                                                 \
+  ORDER BY ASC(nfo:fileName(?urn))                                    \
+  OFFSET %i LIMIT %i"
+
+#define TRACKER_BROWSE_DIRECTORY_CONT_REQUEST "                       \
+  SELECT %s                                                           \
+  WHERE {                                                             \
+    { ?urn a nfo:Folder } UNION                                       \
+    { ?urn a nmm:Video } UNION                                        \
+    { ?urn a nmm:Photo } UNION                                        \
+    { ?urn a nmm:MusicPiece } .                                       \
+    ?urn tracker:available ?tr .                                      \
+    ?urn nie:isPartOf <%s>                                            \
+    }                                                                 \
+  ORDER BY ASC(nfo:fileName(?urn))                                    \
+  OFFSET %i LIMIT %i"
+
 #define TRACKER_SEARCH_REQUEST "                                    \
   SELECT %s                                                         \
   WHERE {                                                           \
@@ -94,6 +131,12 @@ typedef enum {
   MEDIA_PROP_FLOAT,
 } tracker_grl_type_t;
 
+typedef enum {
+  TRACKER_BROWSING_MODE_FLAT,
+  TRACKER_BROWSING_MODE_DIRECTORY,
+  TRACKER_BROWSING_MODE_INVALID,
+} tracker_browsing_mode_t;
+
 typedef struct {
   GrlKeyID            grl_key;
   tracker_grl_type_t  grl_key_type;
@@ -115,6 +158,13 @@ struct OperationSpec {
 
 struct _GrlTrackerSourcePriv {
   TrackerSparqlConnection *tracker_connection;
+
+  tracker_browsing_mode_t browsing_mode;
+};
+
+enum {
+  PROP_0,
+  PROP_BROWSING_MODE,
 };
 
 #define GRL_TRACKER_SOURCE_GET_PRIVATE(object)		\
@@ -122,12 +172,25 @@ struct _GrlTrackerSourcePriv {
                                GRL_TRACKER_SOURCE_TYPE,	\
                                GrlTrackerSourcePriv))
 
-static GrlTrackerSource *grl_tracker_source_new (void);
 
 gboolean grl_tracker_plugin_init (GrlPluginRegistry *registry,
                                   const GrlPluginInfo *plugin,
                                   GList *configs);
 
+static GrlTrackerSource *grl_tracker_source_new (void);
+
+static void grl_tracker_source_get_property (GObject    *object,
+                                             guint       prop_id,
+                                             GValue     *value,
+                                             GParamSpec *pspec);
+
+static void grl_tracker_source_set_property (GObject      *object,
+                                             guint         propid,
+                                             const GValue *value,
+                                             GParamSpec   *pspec);
+
+static void grl_tracker_source_finalize (GObject *plugin);
+
 static GrlSupportedOps grl_tracker_source_supported_operations (GrlMetadataSource *metadata_source);
 
 static const GList *grl_tracker_source_supported_keys (GrlMetadataSource *source);
@@ -142,8 +205,15 @@ static void grl_tracker_source_search (GrlMediaSource *source,
 static void grl_tracker_source_metadata (GrlMediaSource *source,
                                          GrlMediaSourceMetadataSpec *ms);
 
+static void grl_tracker_source_browse (GrlMediaSource *source,
+                                       GrlMediaSourceBrowseSpec *bs);
+
 static void setup_key_mappings (void);
 
+static const gchar *tracker_browsing_mode_to_str (tracker_browsing_mode_t mode);
+
+static tracker_browsing_mode_t tracker_browsing_mode_from_str (const gchar *str);
+
 /* ===================== Globals  ================= */
 
 static GHashTable *grl_to_sparql_mapping = NULL;
@@ -156,11 +226,31 @@ grl_tracker_plugin_init (GrlPluginRegistry *registry,
                          const GrlPluginInfo *plugin,
                          GList *configs)
 {
+  GrlConfig *config;
+  gint config_count;
+
   GRL_LOG_DOMAIN_INIT (tracker_log_domain, "tracker");
 
   GRL_DEBUG ("tracker_plugin_init");
 
   GrlTrackerSource *source = grl_tracker_source_new ();
+
+  if (!configs) {
+    GRL_WARNING ("Configuration not provided! Using default configuration.");
+  } else {
+    config_count = g_list_length (configs);
+    if (config_count > 1) {
+      GRL_WARNING ("Provided %i configs, but will only use one", config_count);
+    }
+
+    config = GRL_CONFIG (configs->data);
+
+    g_object_set (G_OBJECT (source),
+                  "browsing-mode",
+                  grl_config_get_string (config, "flat-browsing-view"),
+                  NULL);
+  }
+
   grl_plugin_registry_register_source (registry,
                                        plugin,
                                        GRL_MEDIA_PLUGIN (source),
@@ -202,33 +292,33 @@ grl_tracker_source_new (void)
 G_DEFINE_TYPE (GrlTrackerSource, grl_tracker_source, GRL_TYPE_MEDIA_SOURCE);
 
 static void
-grl_tracker_source_finalize (GObject *object)
-{
-  GrlTrackerSource *self;
-
-  self = GRL_TRACKER_SOURCE (object);
-  if (self->priv->tracker_connection) {
-    g_object_unref (self->priv->tracker_connection);
-  }
-
-  G_OBJECT_CLASS (grl_tracker_source_parent_class)->finalize (object);
-}
-
-static void
 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->browse   = grl_tracker_source_browse;
+  source_class->metadata = grl_tracker_source_metadata;
   source_class->query    = grl_tracker_source_query;
   source_class->search   = grl_tracker_source_search;
-  source_class->metadata = grl_tracker_source_metadata;
 
   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_class->finalize     = grl_tracker_source_finalize;
+  g_class->get_property = grl_tracker_source_get_property;
+  g_class->set_property = grl_tracker_source_set_property;
+
+  g_object_class_install_property (g_class,
+                                   PROP_BROWSING_MODE,
+                                   g_param_spec_string ("browsing-mode",
+                                                        "browsing-mode",
+                                                        "Method used to browse a tracker source (flat,directory)",
+                                                        "directory",
+                                                        G_PARAM_READABLE
+                                                        | G_PARAM_WRITABLE
+                                                        | G_PARAM_STATIC_NAME));
 
   g_type_class_add_private (klass, sizeof (GrlTrackerSourcePriv));
 
@@ -239,10 +329,98 @@ static void
 grl_tracker_source_init (GrlTrackerSource *source)
 {
   source->priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+
+  source->priv->browsing_mode = TRACKER_BROWSING_MODE_DIRECTORY;
+}
+
+static void
+grl_tracker_source_finalize (GObject *object)
+{
+  GrlTrackerSource *self;
+
+  self = GRL_TRACKER_SOURCE (object);
+  if (self->priv->tracker_connection) {
+    g_object_unref (self->priv->tracker_connection);
+  }
+
+  G_OBJECT_CLASS (grl_tracker_source_parent_class)->finalize (object);
+}
+
+static void
+grl_tracker_source_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (object);
+
+  switch (prop_id) {
+  case PROP_BROWSING_MODE:
+    g_value_set_string (value,
+                        g_strdup (tracker_browsing_mode_to_str (priv->browsing_mode)));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+grl_tracker_source_set_property (GObject      *object,
+                                 guint         propid,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+
+{
+  GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (object);
+
+  switch (propid) {
+  case PROP_BROWSING_MODE:
+    {
+      tracker_browsing_mode_t mode =
+        tracker_browsing_mode_from_str (g_value_get_string (value));
+      if (mode != TRACKER_BROWSING_MODE_INVALID)
+        priv->browsing_mode = mode;
+    }
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
+  }
 }
 
 /* ======================= Utilities ==================== */
 
+static const gchar *
+tracker_browsing_mode_to_str (tracker_browsing_mode_t mode)
+{
+  switch (mode) {
+  case TRACKER_BROWSING_MODE_FLAT:
+    return "flat";
+
+  case TRACKER_BROWSING_MODE_DIRECTORY:
+    return "directory";
+
+  default:
+    return "invalid";
+  }
+
+  return "invalid";
+}
+
+static tracker_browsing_mode_t
+tracker_browsing_mode_from_str (const gchar *str)
+{
+  if (str == NULL)
+    return TRACKER_BROWSING_MODE_INVALID;
+  if (!strcmp (str, "flat"))
+    return TRACKER_BROWSING_MODE_FLAT;
+  if (!strcmp (str, "directory"))
+    return TRACKER_BROWSING_MODE_DIRECTORY;
+  return TRACKER_BROWSING_MODE_INVALID;
+}
+
 static gchar *
 build_flavored_key (gchar *key, const gchar *flavor)
 {
@@ -326,7 +504,7 @@ setup_key_mappings (void)
                       "audio");
 
   insert_key_mapping (GRL_METADATA_KEY_FRAMERATE,
-                      MEDIA_PROP_INT,
+                      MEDIA_PROP_FLOAT,
                       "nfo:frameRate(?urn)",
                       "video");
 
@@ -442,8 +620,12 @@ build_grilo_media (const gchar *rdf_type)
       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_FOLDER)) {
+      media = grl_media_box_new ();
     } else if (g_str_has_suffix (rdf_single_type[i], RDF_TYPE_BOX)) {
       media = grl_media_box_new ();
+    } else {
+      media = grl_media_new ();
     }
     i--;
   }
@@ -466,6 +648,9 @@ fill_grilo_media_from_sparql (GrlMedia *media,
     const gchar *str_val;
   } val;
 
+  if (assoc == NULL)
+    return;
+
   GRL_DEBUG ("\tSetting media prop (col=%i/var=%s//prop=%s/type=%i) %s",
              column,
              sparql_key,
@@ -623,7 +808,7 @@ grl_tracker_source_supported_operations (GrlMetadataSource *metadata_source)
   GrlTrackerSource *source;
 
   source = GRL_TRACKER_SOURCE (metadata_source);
-  caps = GRL_OP_QUERY | GRL_OP_SEARCH | GRL_OP_METADATA;
+  caps = GRL_OP_BROWSE | GRL_OP_METADATA | GRL_OP_QUERY | GRL_OP_SEARCH;
 
   return caps;
 }
@@ -823,3 +1008,69 @@ grl_tracker_source_metadata (GrlMediaSource *source,
   if (sparql_final != NULL)
     g_free (sparql_final);
 }
+
+static void
+grl_tracker_source_browse (GrlMediaSource           *source,
+                           GrlMediaSourceBrowseSpec *bs)
+{
+  GrlTrackerSourcePriv *priv  = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+  gchar                *sparql_select;
+  gchar                *sparql_final;
+  GError               *error = NULL;
+  struct OperationSpec *os;
+
+  GRL_DEBUG ("grl_tracker_source_browse");
+
+  if (priv->tracker_connection == NULL) {
+    error = g_error_new (GRL_CORE_ERROR,
+                         GRL_CORE_ERROR_SEARCH_FAILED,
+                         "No tracker connection");
+    goto send_error;
+  }
+
+  sparql_select = get_select_string (source, bs->keys);
+  if (priv->browsing_mode == TRACKER_BROWSING_MODE_FLAT) {
+    sparql_final = g_strdup_printf (TRACKER_BROWSE_FLAT_REQUEST,
+                                    sparql_select, bs->skip, bs->count);
+  } else {
+    if (bs->container == NULL ||
+        grl_media_get_id (bs->container) == NULL) {
+      sparql_final = g_strdup_printf (TRACKER_BROWSE_DIRECTORY_ROOT_REQUEST,
+                                      sparql_select, bs->skip, bs->count);
+    } else {
+      sparql_final = g_strdup_printf (TRACKER_BROWSE_DIRECTORY_CONT_REQUEST,
+                                      sparql_select,
+                                      grl_media_get_id (bs->container),
+                                      bs->skip, bs->count);
+    }
+  }
+
+  GRL_DEBUG ("select: '%s'", sparql_final);
+
+  os = g_slice_new0 (struct OperationSpec);
+  os->source       = bs->source;
+  os->priv         = priv;
+  os->operation_id = bs->browse_id;
+  os->keys         = grl_tracker_source_supported_keys (GRL_METADATA_SOURCE (source));
+  os->skip         = bs->skip;
+  os->count        = bs->count;
+  os->callback     = bs->callback;
+  os->user_data    = bs->user_data;
+
+  tracker_sparql_connection_query_async (priv->tracker_connection,
+                                         sparql_final,
+                                         NULL,
+                                         (GAsyncReadyCallback) tracker_query_cb,
+                                         os);
+
+  if (sparql_select != NULL)
+    g_free (sparql_select);
+  if (sparql_final != NULL)
+    g_free (sparql_final);
+
+  return;
+
+ send_error:
+  bs->callback (bs->source, bs->browse_id, NULL, 0, bs->user_data, error);
+  g_error_free (error);
+}
-- 
1.7.2.3



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