[rygel] core,tracker: Sort before slicing



commit 7abecff3a25b2c9482a58b18e2f92ae769528148
Author: Lukasz Pawlik <lukasz pawlik comarch com>
Date:   Sun Aug 5 18:54:05 2012 +0200

    core,tracker: Sort before slicing
    
    Fixes inconsistencies in returned results.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=661482

 src/librygel-server/rygel-browse.vala              |    3 +
 src/librygel-server/rygel-client-hacks.vala        |    2 +
 src/librygel-server/rygel-item-creator.vala        |    1 +
 src/librygel-server/rygel-media-container.vala     |    2 +
 src/librygel-server/rygel-search.vala              |    2 +
 .../rygel-searchable-container.vala                |    6 ++-
 src/librygel-server/rygel-simple-container.vala    |   12 +++-
 src/librygel-server/rygel-wmp-hacks.vala           |    2 +
 src/librygel-server/rygel-xbox-hacks.vala          |    2 +
 src/plugins/external/rygel-external-container.vala |   12 +++-
 .../external/rygel-external-dummy-container.vala   |   12 ++--
 .../rygel-media-export-db-container.vala           |   12 +++-
 .../rygel-media-export-leaf-query-container.vala   |   11 ++-
 .../rygel-media-export-node-query-container.vala   |   11 ++-
 .../rygel-media-export-null-container.vala         |   10 ++-
 .../rygel-media-export-query-container.vala        |    1 +
 .../rygel-media-export-root-container.vala         |    4 +
 .../rygel-tracker-category-all-container.vala      |    2 +
 .../tracker/rygel-tracker-search-container.vala    |   60 ++++++++++++++++++--
 19 files changed, 131 insertions(+), 36 deletions(-)
---
diff --git a/src/librygel-server/rygel-browse.vala b/src/librygel-server/rygel-browse.vala
index a4b6119..b9319d4 100644
--- a/src/librygel-server/rygel-browse.vala
+++ b/src/librygel-server/rygel-browse.vala
@@ -110,9 +110,12 @@ internal class Rygel.Browse: Rygel.MediaQueryAction {
                this.requested_count,
                this.object_id,
                this.index);
+
         var children = yield container.get_children (this.index,
                                                      this.requested_count,
+                                                     this.sort_criteria,
                                                      this.cancellable);
+
         debug ("Fetched %u children of container '%s' from index %u.",
                this.requested_count,
                this.object_id,
diff --git a/src/librygel-server/rygel-client-hacks.vala b/src/librygel-server/rygel-client-hacks.vala
index 2f6f72a..3fd9040 100644
--- a/src/librygel-server/rygel-client-hacks.vala
+++ b/src/librygel-server/rygel-client-hacks.vala
@@ -84,12 +84,14 @@ internal abstract class Rygel.ClientHacks : GLib.Object {
                                          uint                offset,
                                          uint                max_count,
                                          out uint            total_matches,
+                                         string              sort_criteria,
                                          Cancellable?        cancellable)
                                          throws Error {
         return yield container.search (expression,
                                        offset,
                                        max_count,
                                        out total_matches,
+                                       sort_criteria,
                                        cancellable);
     }
 
diff --git a/src/librygel-server/rygel-item-creator.vala b/src/librygel-server/rygel-item-creator.vala
index ad29cc1..3815e85 100644
--- a/src/librygel-server/rygel-item-creator.vala
+++ b/src/librygel-server/rygel-item-creator.vala
@@ -235,6 +235,7 @@ internal class Rygel.ItemCreator: GLib.Object, Rygel.StateMachine {
                                                       0,
                                                       1,
                                                       out total_matches,
+                                                      "",
                                                       this.cancellable);
             if (result.size > 0) {
                 this.didl_item.upnp_class = upnp_class;
diff --git a/src/librygel-server/rygel-media-container.vala b/src/librygel-server/rygel-media-container.vala
index 8e6f420..621f787 100644
--- a/src/librygel-server/rygel-media-container.vala
+++ b/src/librygel-server/rygel-media-container.vala
@@ -106,12 +106,14 @@ public abstract class Rygel.MediaContainer : MediaObject {
      *
      * @param offset zero-based index of the first item to return
      * @param max_count maximum number of objects to return
+     * @param sort_criteria sorting order of objects to return
      * @param cancellable optional cancellable for this operation
      *
      * @return A list of media objects.
      */
     public async abstract MediaObjects? get_children (uint         offset,
                                                       uint         max_count,
+                                                      string       sort_criteria,
                                                       Cancellable? cancellable)
                                                       throws Error;
 
diff --git a/src/librygel-server/rygel-search.vala b/src/librygel-server/rygel-search.vala
index b050eff..d35be7e 100644
--- a/src/librygel-server/rygel-search.vala
+++ b/src/librygel-server/rygel-search.vala
@@ -75,12 +75,14 @@ internal class Rygel.Search:  Rygel.MediaQueryAction {
                                             this.index,
                                             this.requested_count,
                                             out this.total_matches,
+                                            this.sort_criteria,
                                             this.cancellable);
         } else {
             return yield container.search (parser.expression,
                                            this.index,
                                            this.requested_count,
                                            out this.total_matches,
+                                           this.sort_criteria,
                                            this.cancellable);
         }
     }
diff --git a/src/librygel-server/rygel-searchable-container.vala b/src/librygel-server/rygel-searchable-container.vala
index faf2868..60d61b0 100644
--- a/src/librygel-server/rygel-searchable-container.vala
+++ b/src/librygel-server/rygel-searchable-container.vala
@@ -45,6 +45,7 @@ public interface Rygel.SearchableContainer : MediaContainer {
                                                 uint              offset,
                                                 uint              max_count,
                                                 out uint          total_matches,
+                                                string            sort_criteria,
                                                 Cancellable?      cancellable)
                                                 throws Error;
 
@@ -68,12 +69,14 @@ public interface Rygel.SearchableContainer : MediaContainer {
                                               uint              offset,
                                               uint              max_count,
                                               out uint          total_matches,
+                                              string            sort_criteria,
                                               Cancellable?      cancellable)
                                               throws Error {
         var result = new MediaObjects ();
 
         var children = yield this.get_children (0,
                                                 this.child_count,
+                                                sort_criteria,
                                                 cancellable);
 
         // The maximum number of results we need to be able to slice-out
@@ -99,7 +102,6 @@ public interface Rygel.SearchableContainer : MediaContainer {
         if (limit == 0 || result.size < limit) {
             // Then search in the children
             var child_limit = (limit == 0)? 0: limit - result.size;
-
             var child_results = yield this.search_in_children (expression,
                                                                children,
                                                                child_limit,
@@ -158,6 +160,7 @@ public interface Rygel.SearchableContainer : MediaContainer {
                                          0,
                                          1,
                                          out total_matches,
+                                         "",
                                          cancellable);
         if (results.size > 0) {
             return results[0];
@@ -182,6 +185,7 @@ public interface Rygel.SearchableContainer : MediaContainer {
                                                            0,
                                                            limit,
                                                            out tmp,
+                                                           "",
                                                            cancellable);
 
                 result.add_all (child_result);
diff --git a/src/librygel-server/rygel-simple-container.vala b/src/librygel-server/rygel-simple-container.vala
index 4b82bb4..08cb7d8 100644
--- a/src/librygel-server/rygel-simple-container.vala
+++ b/src/librygel-server/rygel-simple-container.vala
@@ -121,10 +121,12 @@ public class Rygel.SimpleContainer : Rygel.MediaContainer,
         return unique;
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws Error {
+    public override async MediaObjects? get_children (
+                                                     uint         offset,
+                                                     uint         max_count,
+                                                     string       sort_criteria,
+                                                     Cancellable? cancellable)
+                                                     throws Error {
         uint stop = offset + max_count;
         stop = stop.clamp (0, this.child_count);
 
@@ -188,12 +190,14 @@ public class Rygel.SimpleContainer : Rygel.MediaContainer,
                                        uint              offset,
                                        uint              max_count,
                                        out uint          total_matches,
+                                       string            sort_criteria,
                                        Cancellable?      cancellable)
                                        throws Error {
         return yield this.simple_search (expression,
                                          offset,
                                          max_count,
                                          out total_matches,
+                                         sort_criteria,
                                          cancellable);
     }
 
diff --git a/src/librygel-server/rygel-wmp-hacks.vala b/src/librygel-server/rygel-wmp-hacks.vala
index 7e9d23d..91cae3c 100644
--- a/src/librygel-server/rygel-wmp-hacks.vala
+++ b/src/librygel-server/rygel-wmp-hacks.vala
@@ -35,6 +35,7 @@ internal class Rygel.WMPHacks : ClientHacks {
                                          uint                offset,
                                          uint                requested,
                                          out uint            total_matches,
+                                         string              sort_criteria,
                                          Cancellable?        cancellable)
                                          throws Error {
         // Drop the limit. WMP has a problem if we don't know the number of
@@ -46,6 +47,7 @@ internal class Rygel.WMPHacks : ClientHacks {
                                        offset,
                                        0,
                                        out total_matches,
+                                       sort_criteria,
                                        cancellable);
     }
 }
diff --git a/src/librygel-server/rygel-xbox-hacks.vala b/src/librygel-server/rygel-xbox-hacks.vala
index b2f046c..fc4e3dd 100644
--- a/src/librygel-server/rygel-xbox-hacks.vala
+++ b/src/librygel-server/rygel-xbox-hacks.vala
@@ -130,6 +130,7 @@ internal class Rygel.XBoxHacks : ClientHacks {
                                          uint                offset,
                                          uint                max_count,
                                          out uint            total_matches,
+                                         string              sort_criteria,
                                          Cancellable?        cancellable)
                                          throws Error {
         var set_total_matches = false;
@@ -159,6 +160,7 @@ internal class Rygel.XBoxHacks : ClientHacks {
                                               offset,
                                               max_count,
                                               out total_matches,
+                                              sort_criteria,
                                               cancellable);
         if (total_matches == 0 && set_total_matches) {
             total_matches = results.size;
diff --git a/src/plugins/external/rygel-external-container.vala b/src/plugins/external/rygel-external-container.vala
index 9f8306f..a7648a6 100644
--- a/src/plugins/external/rygel-external-container.vala
+++ b/src/plugins/external/rygel-external-container.vala
@@ -74,10 +74,12 @@ public class Rygel.External.Container : Rygel.MediaContainer,
         }
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws GLib.Error {
+    public override async MediaObjects? get_children (
+                                                     uint         offset,
+                                                     uint         max_count,
+                                                     string       sort_criteria,
+                                                     Cancellable? cancellable)
+                                                     throws GLib.Error {
         string[] filter = {};
 
         foreach (var object_prop in MediaObjectProxy.PROPERTIES) {
@@ -102,6 +104,7 @@ public class Rygel.External.Container : Rygel.MediaContainer,
                                        uint              offset,
                                        uint              max_count,
                                        out uint          total_matches,
+                                       string            sort_criteria,
                                        Cancellable?      cancellable)
                                        throws GLib.Error {
         if (expression == null || !this.searchable) {
@@ -110,6 +113,7 @@ public class Rygel.External.Container : Rygel.MediaContainer,
                                              offset,
                                              max_count,
                                              out total_matches,
+                                             sort_criteria,
                                              cancellable);
         }
 
diff --git a/src/plugins/external/rygel-external-dummy-container.vala b/src/plugins/external/rygel-external-dummy-container.vala
index 7ccb6f3..b1ba379 100644
--- a/src/plugins/external/rygel-external-dummy-container.vala
+++ b/src/plugins/external/rygel-external-dummy-container.vala
@@ -38,14 +38,16 @@ internal class Rygel.External.DummyContainer : MediaContainer {
         base (id, parent, title, (int) child_count);
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws Error {
+    public override async MediaObjects? get_children (
+                                                     uint         offset,
+                                                     uint         max_count,
+                                                     string       sort_criteria,
+                                                     Cancellable? cancellable)
+                                                     throws Error {
         return new MediaObjects ();
     }
 
-    public override async MediaObject? find_object (string       id,
+     public override async MediaObject? find_object (string       id,
                                                     Cancellable? cancellable)
                                                     throws Error {
         return null;
diff --git a/src/plugins/media-export/rygel-media-export-db-container.vala b/src/plugins/media-export/rygel-media-export-db-container.vala
index 03e18db..3477983 100644
--- a/src/plugins/media-export/rygel-media-export-db-container.vala
+++ b/src/plugins/media-export/rygel-media-export-db-container.vala
@@ -47,10 +47,12 @@ public class Rygel.MediaExport.DBContainer : MediaContainer,
         }
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws GLib.Error {
+    public override async MediaObjects? get_children (
+                                                     uint         offset,
+                                                     uint         max_count,
+                                                     string       sort_criteria,
+                                                     Cancellable? cancellable)
+                                                     throws GLib.Error {
         return this.media_db.get_children (this, offset, max_count);
     }
 
@@ -58,6 +60,7 @@ public class Rygel.MediaExport.DBContainer : MediaContainer,
                                                uint              offset,
                                                uint              max_count,
                                                out uint          total_matches,
+                                               string            sort_criteria,
                                                Cancellable?      cancellable)
                                                throws GLib.Error {
         MediaObjects children = null;
@@ -75,6 +78,7 @@ public class Rygel.MediaExport.DBContainer : MediaContainer,
                                                      offset,
                                                      max_count,
                                                      out total_matches,
+                                                     sort_criteria,
                                                      cancellable);
             } else {
                 throw error;
diff --git a/src/plugins/media-export/rygel-media-export-leaf-query-container.vala b/src/plugins/media-export/rygel-media-export-leaf-query-container.vala
index f363290..bd82a88 100644
--- a/src/plugins/media-export/rygel-media-export-leaf-query-container.vala
+++ b/src/plugins/media-export/rygel-media-export-leaf-query-container.vala
@@ -26,15 +26,18 @@ internal class Rygel.MediaExport.LeafQueryContainer : QueryContainer {
         base (cache, expression, id, name);
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws GLib.Error {
+    public override async MediaObjects? get_children
+                                        (uint         offset,
+                                         uint         max_count,
+                                         string       sort_criteria,
+                                         Cancellable? cancellable)
+                                         throws GLib.Error {
         uint total_matches;
         var children = yield this.search (null,
                                           offset,
                                           max_count,
                                           out total_matches,
+                                          sort_criteria,
                                           cancellable);
         foreach (var child in children) {
             child.parent = this;
diff --git a/src/plugins/media-export/rygel-media-export-node-query-container.vala b/src/plugins/media-export/rygel-media-export-node-query-container.vala
index 152eddd..1d40084 100644
--- a/src/plugins/media-export/rygel-media-export-node-query-container.vala
+++ b/src/plugins/media-export/rygel-media-export-node-query-container.vala
@@ -43,14 +43,17 @@ internal class Rygel.MediaExport.NodeQueryContainer : QueryContainer {
 
     // MediaContainer overrides
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws GLib.Error {
+    public override async MediaObjects? get_children
+                                        (uint         offset,
+                                         uint         max_count,
+                                         string       sort_criteria,
+                                         Cancellable? cancellable)
+                                         throws GLib.Error {
         var children = new MediaObjects ();
         var data = this.media_db.get_object_attribute_by_search_expression
                                         (this.attribute,
                                          this.expression,
+                                         // sort criteria
                                          offset,
                                          max_count);
 
diff --git a/src/plugins/media-export/rygel-media-export-null-container.vala b/src/plugins/media-export/rygel-media-export-null-container.vala
index f046959..6309fbc 100644
--- a/src/plugins/media-export/rygel-media-export-null-container.vala
+++ b/src/plugins/media-export/rygel-media-export-null-container.vala
@@ -30,10 +30,12 @@ internal class Rygel.NullContainer : MediaContainer {
         base.root ("MediaExport", 0);
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
-                                                      Cancellable? cancellable)
-                                                      throws Error {
+    public override async MediaObjects? get_children (
+                                                     uint         offset,
+                                                     uint         max_count,
+                                                     string       sort_criteria,
+                                                     Cancellable? cancellable)
+                                                     throws Error {
         return new MediaObjects ();
     }
 
diff --git a/src/plugins/media-export/rygel-media-export-query-container.vala b/src/plugins/media-export/rygel-media-export-query-container.vala
index 3800c62..0833f44 100644
--- a/src/plugins/media-export/rygel-media-export-query-container.vala
+++ b/src/plugins/media-export/rygel-media-export-query-container.vala
@@ -49,6 +49,7 @@ internal abstract class Rygel.MediaExport.QueryContainer : DBContainer {
                                                 uint              offset,
                                                 uint              max_count,
                                                 out uint          total_matches,
+                                                string            sort_criteria,
                                                 Cancellable?      cancellable)
                                                 throws GLib.Error {
         MediaObjects children = null;
diff --git a/src/plugins/media-export/rygel-media-export-root-container.vala b/src/plugins/media-export/rygel-media-export-root-container.vala
index 723be32..3b15685 100644
--- a/src/plugins/media-export/rygel-media-export-root-container.vala
+++ b/src/plugins/media-export/rygel-media-export-root-container.vala
@@ -137,6 +137,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
                                                 uint              offset,
                                                 uint              max_count,
                                                 out uint          total_matches,
+                                                string            sort_criteria,
                                                 Cancellable?      cancellable)
                                                 throws GLib.Error {
          if (expression == null) {
@@ -144,6 +145,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
                                       offset,
                                       max_count,
                                       out total_matches,
+                                      sort_criteria,
                                       cancellable);
         }
 
@@ -165,6 +167,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
         if (query_container != null) {
             list = yield query_container.get_children (offset,
                                                        max_count,
+                                                       sort_criteria,
                                                        cancellable);
             total_matches = query_container.child_count;
 
@@ -180,6 +183,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
                                       offset,
                                       max_count,
                                       out total_matches,
+                                      sort_criteria,
                                       cancellable);
         }
     }
diff --git a/src/plugins/tracker/rygel-tracker-category-all-container.vala b/src/plugins/tracker/rygel-tracker-category-all-container.vala
index d33643f..a1a1185 100644
--- a/src/plugins/tracker/rygel-tracker-category-all-container.vala
+++ b/src/plugins/tracker/rygel-tracker-category-all-container.vala
@@ -103,12 +103,14 @@ public class Rygel.Tracker.CategoryAllContainer : SearchContainer,
                                        uint              offset,
                                        uint              max_count,
                                        out uint          total_matches,
+                                       string            sort_criteria,
                                        Cancellable?      cancellable)
                                        throws Error {
         return yield this.simple_search (expression,
                                          offset,
                                          max_count,
                                          out total_matches,
+                                         sort_criteria,
                                          cancellable);
     }
 
diff --git a/src/plugins/tracker/rygel-tracker-search-container.vala b/src/plugins/tracker/rygel-tracker-search-container.vala
index 6f83584..29ed77c 100644
--- a/src/plugins/tracker/rygel-tracker-search-container.vala
+++ b/src/plugins/tracker/rygel-tracker-search-container.vala
@@ -35,6 +35,8 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
     /* class-wide constants */
     private const string MODIFIED_PROPERTY = "nfo:fileLastModified";
 
+    private string sort_criteria = "";
+
     public SelectionQuery query;
     public ItemFactory item_factory;
 
@@ -105,8 +107,9 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
         }
     }
 
-    public override async MediaObjects? get_children (uint         offset,
-                                                      uint         max_count,
+    public override async MediaObjects? get_children (uint       offset,
+                                                      uint       max_count,
+                                                      string     sort_criteria,
                                                       Cancellable? cancellable)
                                                       throws GLib.Error {
         var expression = new RelationalExpression ();
@@ -116,6 +119,8 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
 
         uint total_matches;
 
+        this.sort_criteria = sort_criteria;
+
         return yield this.execute_query (expression,
                                          offset,
                                          max_count,
@@ -133,7 +138,8 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
 
         var query = this.create_query (expression as RelationalExpression,
                                        (int) offset,
-                                       (int) max_count);
+                                       (int) max_count,
+                                       this.sort_criteria);
 
         if (query != null) {
             yield query.execute (this.resources);
@@ -233,14 +239,20 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
     }
 
     private SelectionQuery? create_query (RelationalExpression? expression,
-                                          int                   offset,
-                                          int                   max_count) {
+                                          int offset,
+                                          int max_count,
+                                          string sort_criteria = "") {
         if (expression.operand1 == "upnp:class" &&
             !this.item_factory.upnp_class.has_prefix (expression.operand2)) {
             return null;
         }
 
-        var query = new SelectionQuery.clone (this.query);
+        SelectionQuery query;
+        if (sort_criteria == null || sort_criteria == "") {
+            query = new SelectionQuery.clone (this.query);
+        } else {
+            query = create_sorted_query ();
+        }
 
         if (expression.operand1 == "@parentID") {
             if (!expression.compare_string (this.id)) {
@@ -257,10 +269,46 @@ public class Rygel.Tracker.SearchContainer : SimpleContainer {
 
         query.offset = offset;
         query.max_count = max_count;
+        this.sort_criteria = "";
 
         return query;
     }
 
+    private SelectionQuery? create_sorted_query () {
+         var key_chain_map = UPnPPropertyMap.get_property_map ();
+         var sort_props = sort_criteria.split (",");
+         string order = "";
+         ArrayList<string> variables = new ArrayList<string> ();
+         ArrayList<string> filters = new ArrayList<string> ();
+
+         variables.add_all (this.query.variables);
+         filters.add_all (this.query.filters);
+
+         foreach (string s in sort_props) {
+             var key = key_chain_map[s.substring(1)];
+             if (key.index_of (SelectionQuery.ITEM_VARIABLE) == 0) {
+                 continue;
+             }
+
+             if (s.has_prefix("-")) {
+                 order += "DESC (" +
+                           key + ") ";
+             } else {
+                 order += key + " ";
+             }
+         }
+
+         if (order == "") {
+             order = this.query.order_by;
+         }
+
+         return new SelectionQuery (
+                                variables,
+                                new QueryTriplets.clone(this.query.triplets),
+                                filters,
+                                order);
+    }
+
     private string? urn_to_utf8 (string urn) {
         var urn_builder = new StringBuilder ();
         unowned string s = urn;



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