[rygel] tracker: Use property map in meta-data containers



commit e7993915a35f9e56e3abc921d5a31ac2df78aafc
Author: Jens Georg <mail jensge org>
Date:   Sat Jul 14 18:39:25 2012 +0200

    tracker: Use property map in meta-data containers
    
    Split off Tags container since tags are multi-valued and don't work with
    property functions

 src/plugins/tracker/Makefile.am                    |    1 +
 src/plugins/tracker/rygel-tracker-albums.vala      |    6 +-
 src/plugins/tracker/rygel-tracker-artists.vala     |    6 +-
 src/plugins/tracker/rygel-tracker-genre.vala       |    4 +-
 .../tracker/rygel-tracker-key-chain-map.vala       |    1 -
 .../rygel-tracker-metadata-multivalues.vala        |  197 ++++++++++++++++++++
 .../tracker/rygel-tracker-metadata-values.vala     |   42 +---
 src/plugins/tracker/rygel-tracker-tags.vala        |    3 +-
 src/plugins/tracker/rygel-tracker-titles.vala      |    4 +-
 src/plugins/tracker/rygel-tracker-years.vala       |    4 +-
 10 files changed, 217 insertions(+), 51 deletions(-)
---
diff --git a/src/plugins/tracker/Makefile.am b/src/plugins/tracker/Makefile.am
index c50394e..446f7de 100644
--- a/src/plugins/tracker/Makefile.am
+++ b/src/plugins/tracker/Makefile.am
@@ -13,6 +13,7 @@ librygel_tracker_la_SOURCES = \
 	rygel-tracker-videos.vala \
 	rygel-tracker-pictures.vala \
 	rygel-tracker-metadata-values.vala \
+	rygel-tracker-metadata-multivalues.vala \
 	rygel-tracker-tags.vala \
 	rygel-tracker-years.vala \
 	rygel-tracker-titles.vala \
diff --git a/src/plugins/tracker/rygel-tracker-albums.vala b/src/plugins/tracker/rygel-tracker-albums.vala
index 8fcee2d..7fc7c6c 100644
--- a/src/plugins/tracker/rygel-tracker-albums.vala
+++ b/src/plugins/tracker/rygel-tracker-albums.vala
@@ -26,15 +26,11 @@
  */
 public class Rygel.Tracker.Albums : MetadataValues {
     public Albums (Music parent) {
-        var key_chain = new string[] { "nmm:musicAlbum",
-                                       "nmm:albumTitle",
-                                       null };
-
         base (parent.id + "Albums",
               parent,
               _("Albums"),
               parent.item_factory,
-              key_chain,
+              "upnp:album",
               MediaContainer.MUSIC_ALBUM);
     }
 }
diff --git a/src/plugins/tracker/rygel-tracker-artists.vala b/src/plugins/tracker/rygel-tracker-artists.vala
index 646b4ab..73aab9a 100644
--- a/src/plugins/tracker/rygel-tracker-artists.vala
+++ b/src/plugins/tracker/rygel-tracker-artists.vala
@@ -26,15 +26,11 @@
  */
 public class Rygel.Tracker.Artists : MetadataValues {
     public Artists (Music parent) {
-        var key_chain = new string[] { "nmm:performer",
-                                       "nmm:artistName",
-                                       null };
-
         base (parent.id + "Artists",
               parent,
               _("Artists"),
               parent.item_factory,
-              key_chain,
+              "upnp:artist",
               MediaContainer.MUSIC_ARTIST);
     }
 }
diff --git a/src/plugins/tracker/rygel-tracker-genre.vala b/src/plugins/tracker/rygel-tracker-genre.vala
index 4fac786..bf6acb7 100644
--- a/src/plugins/tracker/rygel-tracker-genre.vala
+++ b/src/plugins/tracker/rygel-tracker-genre.vala
@@ -26,13 +26,11 @@
  */
 public class Rygel.Tracker.Genre : MetadataValues {
     public Genre (Music parent) {
-        var key_chain = new string[] { "nfo:genre", null };
-
         base (parent.id + "Genre",
               parent,
               _("Genre"),
               parent.item_factory,
-              key_chain,
+              "upnp:genre",
               MediaContainer.MUSIC_GENRE);
     }
 }
diff --git a/src/plugins/tracker/rygel-tracker-key-chain-map.vala b/src/plugins/tracker/rygel-tracker-key-chain-map.vala
index 9ae0264..bcbbd42 100644
--- a/src/plugins/tracker/rygel-tracker-key-chain-map.vala
+++ b/src/plugins/tracker/rygel-tracker-key-chain-map.vala
@@ -124,4 +124,3 @@ public class Rygel.Tracker.KeyChainMap : Object {
         this.add_function (property, str.str);
     }
 }
-
diff --git a/src/plugins/tracker/rygel-tracker-metadata-multivalues.vala b/src/plugins/tracker/rygel-tracker-metadata-multivalues.vala
new file mode 100644
index 0000000..0cd1ad3
--- /dev/null
+++ b/src/plugins/tracker/rygel-tracker-metadata-multivalues.vala
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
+ * Copyright (C) 2008-2012 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali <zeenix gmail com>
+ *         Jens Georg <jensg openismus com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using GUPnP;
+using Gee;
+using Tracker;
+
+/**
+ * Container listing possible values of a particuler Tracker metadata key.
+ */
+public abstract class Rygel.Tracker.MetadataMultiValues : Rygel.SimpleContainer {
+    /* class-wide constants */
+    private const string TRACKER_SERVICE = "org.freedesktop.Tracker1";
+    private const string RESOURCES_PATH = "/org/freedesktop/Tracker1/Resources";
+
+    private ItemFactory item_factory;
+    private bool update_in_progress = false;
+
+    // In tracker 0.7, we might don't get values of keys in place so you need a
+    // chain of keys to reach to final destination. For instances:
+    // nmm:Performer -> nmm:artistName
+    public string[] key_chain;
+
+    private string child_class;
+
+    private Sparql.Connection resources;
+
+    public MetadataMultiValues (string         id,
+                                MediaContainer parent,
+                                string         title,
+                                ItemFactory    item_factory,
+                                string[]       key_chain,
+                                string?        child_class = null) {
+        base (id, parent, title);
+
+        this.item_factory = item_factory;
+        this.key_chain = key_chain;
+        this.child_class = child_class;
+
+        try {
+            this.resources = Sparql.Connection.get ();
+        } catch (Error error) {
+            critical (_("Failed to create Tracker connection: %s"), error.message);
+
+            return;
+        }
+
+        this.fetch_metadata_values.begin ();
+    }
+
+    internal async void fetch_metadata_values () {
+        if (this.update_in_progress) {
+            return;
+        }
+
+        this.update_in_progress = true;
+        // First thing, clear the existing hierarchy, if any
+        this.clear ();
+
+        int i;
+        var triplets = new QueryTriplets ();
+
+        triplets.add (new QueryTriplet (SelectionQuery.ITEM_VARIABLE,
+                                        "a",
+                                        this.item_factory.category));
+
+        // All variables used in the query
+        var num_keys = this.key_chain.length - 1;
+        var variables = new string[num_keys];
+        for (i = 0; i < num_keys; i++) {
+            variables[i] = "?" + key_chain[i].replace (":", "_");
+
+            string subject;
+            if (i == 0) {
+                subject = SelectionQuery.ITEM_VARIABLE;
+            } else {
+                subject = variables[i - 1];
+            }
+
+            triplets.add (new QueryTriplet (subject,
+                                            this.key_chain[i],
+                                            variables[i]));
+        }
+
+        // Variables to select from query
+        var selected = new ArrayList<string> ();
+        // Last variable is the only thing we are interested in the result
+        var last_variable = variables[num_keys - 1];
+        selected.add ("DISTINCT " + last_variable);
+
+        var query = new SelectionQuery (selected,
+                                        triplets,
+                                        null,
+                                        last_variable);
+
+        try {
+            yield query.execute (this.resources);
+
+            while (query.result.next ()) {
+                string value = query.result.get_string (0);
+
+                if (value == "") {
+                    continue;
+                }
+
+                var title = this.create_title_for_value (value);
+                if (title == null) {
+                    continue;
+                }
+
+                var id = this.create_id_for_title (title);
+                if (id == null || !this.is_child_id_unique (id)) {
+                    continue;
+                }
+
+                // The child container can use the same triplets we used in our
+                // query.
+                var child_triplets = new QueryTriplets.clone (triplets);
+
+                // However we constrain the object of our last triplet.
+                var filters = new ArrayList<string> ();
+                var filter = this.create_filter (child_triplets.last ().obj, value);
+                filters.add (filter);
+
+                var container = new SearchContainer (id,
+                                                     this,
+                                                     title,
+                                                     this.item_factory,
+                                                     child_triplets,
+                                                     filters);
+                if (this.child_class != null) {
+                    container.upnp_class = child_class;
+                }
+
+                this.add_child_container (container);
+            }
+        } catch (Error error) {
+            critical (_("Error getting all values for '%s': %s"),
+                      string.joinv (" -> ", this.key_chain),
+                      error.message);
+            this.update_in_progress = false;
+
+            return;
+        }
+
+
+        this.updated ();
+        this.update_in_progress = false;
+    }
+
+    public override async MediaObject? find_object (string       id,
+                                                    Cancellable? cancellable)
+                                                    throws GLib.Error {
+        if (this.is_our_child (id)) {
+            return yield base.find_object (id, cancellable);
+        } else {
+            return null;
+        }
+    }
+
+    protected virtual string? create_id_for_title (string title) {
+        return this.id + ":" + Uri.escape_string (title, "", true);
+    }
+
+    protected virtual string? create_title_for_value (string value) {
+        return value;
+    }
+
+    protected virtual string create_filter (string variable, string value) {
+        return variable + " = \"" + Query.escape_string (value) + "\"";
+    }
+
+    private bool is_our_child (string id) {
+        return id.has_prefix (this.id + ":");
+    }
+}
diff --git a/src/plugins/tracker/rygel-tracker-metadata-values.vala b/src/plugins/tracker/rygel-tracker-metadata-values.vala
index 11407e9..b333be7 100644
--- a/src/plugins/tracker/rygel-tracker-metadata-values.vala
+++ b/src/plugins/tracker/rygel-tracker-metadata-values.vala
@@ -37,10 +37,7 @@ public abstract class Rygel.Tracker.MetadataValues : Rygel.SimpleContainer {
     private ItemFactory item_factory;
     private bool update_in_progress = false;
 
-    // In tracker 0.7, we might don't get values of keys in place so you need a
-    // chain of keys to reach to final destination. For instances:
-    // nmm:Performer -> nmm:artistName
-    public string[] key_chain;
+    private string property;
 
     private string child_class;
 
@@ -50,12 +47,12 @@ public abstract class Rygel.Tracker.MetadataValues : Rygel.SimpleContainer {
                            MediaContainer parent,
                            string         title,
                            ItemFactory    item_factory,
-                           string[]       key_chain,
+                           string         property,
                            string?        child_class = null) {
         base (id, parent, title);
 
         this.item_factory = item_factory;
-        this.key_chain = key_chain;
+        this.property = property;
         this.child_class = child_class;
 
         try {
@@ -85,34 +82,16 @@ public abstract class Rygel.Tracker.MetadataValues : Rygel.SimpleContainer {
                                         "a",
                                         this.item_factory.category));
 
-        // All variables used in the query
-        var num_keys = this.key_chain.length - 1;
-        var variables = new string[num_keys];
-        for (i = 0; i < num_keys; i++) {
-            variables[i] = "?" + key_chain[i].replace (":", "_");
-
-            string subject;
-            if (i == 0) {
-                subject = SelectionQuery.ITEM_VARIABLE;
-            } else {
-                subject = variables[i - 1];
-            }
-
-            triplets.add (new QueryTriplet (subject,
-                                            this.key_chain[i],
-                                            variables[i]));
-        }
-
-        // Variables to select from query
+        var key_chain_map = KeyChainMap.get_key_chain_map ();
         var selected = new ArrayList<string> ();
-        // Last variable is the only thing we are interested in the result
-        var last_variable = variables[num_keys - 1];
-        selected.add ("DISTINCT " + last_variable);
+        selected.add ("DISTINCT " +
+                      key_chain_map.map_property (this.property) +
+                      " AS x");
 
         var query = new SelectionQuery (selected,
                                         triplets,
                                         null,
-                                        last_variable);
+                                        "?x");
 
         try {
             yield query.execute (this.resources);
@@ -140,7 +119,8 @@ public abstract class Rygel.Tracker.MetadataValues : Rygel.SimpleContainer {
 
                 // However we constrain the object of our last triplet.
                 var filters = new ArrayList<string> ();
-                var filter = this.create_filter (child_triplets.last ().obj, value);
+                var property = key_chain_map.map_property (this.property);
+                var filter = this.create_filter (property, value);
                 filters.add (filter);
 
                 var container = new SearchContainer (id,
@@ -157,7 +137,7 @@ public abstract class Rygel.Tracker.MetadataValues : Rygel.SimpleContainer {
             }
         } catch (Error error) {
             critical (_("Error getting all values for '%s': %s"),
-                      string.joinv (" -> ", this.key_chain),
+                      this.id,
                       error.message);
             this.update_in_progress = false;
 
diff --git a/src/plugins/tracker/rygel-tracker-tags.vala b/src/plugins/tracker/rygel-tracker-tags.vala
index 0f8d2e5..d6fd035 100644
--- a/src/plugins/tracker/rygel-tracker-tags.vala
+++ b/src/plugins/tracker/rygel-tracker-tags.vala
@@ -27,9 +27,10 @@ using Gee;
 /**
  * Container listing all available tag labels in Tracker DB.
  */
-public class Rygel.Tracker.Tags : MetadataValues {
+public class Rygel.Tracker.Tags : MetadataMultiValues {
     /* class-wide constants */
     private const string TITLE = "Tags";
+
     private const string[] KEY_CHAIN = { "nao:hasTag", "nao:prefLabel", null };
 
     public Tags (MediaContainer parent, ItemFactory item_factory) {
diff --git a/src/plugins/tracker/rygel-tracker-titles.vala b/src/plugins/tracker/rygel-tracker-titles.vala
index 3e48d5c..23ef384 100644
--- a/src/plugins/tracker/rygel-tracker-titles.vala
+++ b/src/plugins/tracker/rygel-tracker-titles.vala
@@ -50,14 +50,14 @@
  *   |..
  */
 public class Rygel.Tracker.Titles : MetadataValues {
-    private const string[] KEY_CHAIN = { "nie:title", null };
+    private const string[] KEY_CHAIN = { "dc:title", null };
 
     public Titles (MediaContainer parent, ItemFactory item_factory) {
         base (parent.id + "Titles",
               parent,
               _("Titles"),
               item_factory,
-              KEY_CHAIN);
+              "dc:title");
     }
 
     // The parent class will only create a child container for each unique
diff --git a/src/plugins/tracker/rygel-tracker-years.vala b/src/plugins/tracker/rygel-tracker-years.vala
index 1b6c8f5..9276ae4 100644
--- a/src/plugins/tracker/rygel-tracker-years.vala
+++ b/src/plugins/tracker/rygel-tracker-years.vala
@@ -27,14 +27,12 @@ using Gee;
  * Container listing content hierarchy by year of creation.
  */
 public class Rygel.Tracker.Years : MetadataValues {
-    private const string[] KEY_CHAIN = { "nie:contentCreated", null };
-
     public Years (MediaContainer parent, ItemFactory item_factory) {
         base (parent.id + "Year",
               parent,
               _("Year"),
               item_factory,
-              KEY_CHAIN);
+              "date");
     }
 
     protected override string? create_title_for_value (string value) {



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