[rygel] external: Fetch items on demand



commit 22d1b33c61a51d1d87c917c6b9dc927a310fd45d
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Mon Sep 14 18:34:29 2009 +0300

    external: Fetch items on demand

 src/plugins/external/rygel-external-container.vala |  115 +++++++++++++-------
 src/plugins/external/rygel-external-item.vala      |   28 ++++-
 2 files changed, 97 insertions(+), 46 deletions(-)
---
diff --git a/src/plugins/external/rygel-external-container.vala b/src/plugins/external/rygel-external-container.vala
index b1e4dd9..9946eb5 100644
--- a/src/plugins/external/rygel-external-container.vala
+++ b/src/plugins/external/rygel-external-container.vala
@@ -44,7 +44,7 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
     public string service_name;
     private string object_path;
 
-    private ArrayList<MediaObject> media_objects;
+    private ArrayList<ExternalContainer> containers;
 
     public ExternalContainer (string             id,
                               string             service_name,
@@ -57,7 +57,7 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
         this.object_path = object_path;
         this.host_ip = host_ip;
 
-        this.media_objects = new ArrayList<MediaObject> ();
+        this.containers = new ArrayList<ExternalContainer> ();
 
         try {
             DBus.Connection connection = DBus.Bus.get (DBus.BusType.SESSION);
@@ -75,12 +75,13 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
                                                            object_path,
                                                            CONTAINER_IFACE);
 
-            this.fetch_media_objects ();
+            this.update_container ();
 
             this.actual_container.Updated += this.on_container_updated;
-        } catch (DBus.Error error) {
-            critical ("Failed to fetch root media objects: %s\n",
-                      error.message);
+        } catch (GLib.Error err) {
+            critical ("Failed to fetch information about container '%s': %s\n",
+                      this.id,
+                      err.message);
         }
     }
 
@@ -88,14 +89,40 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
                                        uint               max_count,
                                        Cancellable?       cancellable,
                                        AsyncReadyCallback callback) {
-        uint stop = offset + max_count;
+        var media_objects = new ArrayList <MediaObject> ();
+
+        // First add the child containers
+        media_objects.add_all (this.containers);
+
+        // Then get and add the child items
+        Value value;
+        this.props.Get (CONTAINER_IFACE, "Items", out value);
 
+        unowned PtrArray obj_paths = (PtrArray) value.get_boxed ();
+        if (obj_paths.len > 0) {
+            for (var i = 0; i < obj_paths.len; i++) {
+                var obj_path = (ObjectPath) obj_paths.pdata[i];
+
+                try {
+                    var item = new ExternalItem.for_path (obj_path, this);
+
+                    media_objects.add (item);
+                } catch (GLib.Error err) {
+                    warning ("Error initializable item at '%s': %s. Ignoring..",
+                             obj_path,
+                             err.message);
+                }
+            }
+        }
+
+        uint stop = offset + max_count;
         stop = stop.clamp (0, this.child_count);
-        var containers = this.media_objects.slice ((int) offset, (int) stop);
+
+        var children = media_objects.slice ((int) offset, (int) stop);
 
         var res = new Rygel.SimpleAsyncResult<Gee.List<MediaObject>>
                                                 (this, callback);
-        res.data = containers;
+        res.data = children;
         res.complete_in_idle ();
     }
 
@@ -109,10 +136,17 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
     public override void find_object (string             id,
                                       Cancellable?       cancellable,
                                       AsyncReadyCallback callback) {
-        MediaObject media_object = find_object_sync (id);
-
         var res = new Rygel.SimpleAsyncResult<MediaObject> (this, callback);
 
+        MediaObject media_object = find_container (id);
+        if (media_object == null && ExternalItem.id_valid (id)) {
+            try {
+                media_object = new ExternalItem.for_id (id, this);
+            } catch (GLib.Error err) {
+                res.error = err;
+            }
+        }
+
         res.data = media_object;
         res.complete_in_idle ();
     }
@@ -120,7 +154,12 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
     public override MediaObject? find_object_finish (AsyncResult res)
                                                      throws GLib.Error {
         var simple_res = (Rygel.SimpleAsyncResult<MediaObject>) res;
-        return simple_res.data;
+
+        if (simple_res.error != null) {
+            throw simple_res.error;
+        } else {
+            return simple_res.data;
+        }
     }
 
     public string substitute_keywords (string title) {
@@ -135,32 +174,31 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
     }
 
     // Private methods
-    private MediaObject? find_object_sync (string id) {
-        MediaObject obj = null;
+    private MediaContainer? find_container (string id) {
+        MediaContainer container = null;
 
-        foreach (var tmp in this.media_objects) {
+        foreach (var tmp in this.containers) {
             if (id == tmp.id) {
-                obj = tmp;
-            } else if (tmp is ExternalContainer) {
+                container = tmp;
+            } else {
                 // Check it's children
-                var container = (ExternalContainer) tmp;
-
-                obj = container.find_object_sync (id);
+                container = tmp.find_container (id);
             }
 
-            if (obj != null) {
+            if (container != null) {
                 break;
             }
         }
 
-        return obj;
+        return container;
     }
 
-    private void fetch_media_objects () throws GLib.Error {
-        HashTable<string,Value?> all_props =
-                                    this.props.GetAll (CONTAINER_IFACE);
+    private void update_container () throws GLib.Error {
+        this.containers.clear ();
+
+        Value value;
+        this.props.Get (CONTAINER_IFACE, "Containers", out value);
 
-        var value = all_props.lookup ("Containers");
         unowned PtrArray obj_paths = (PtrArray) value.get_boxed ();
         if (obj_paths.len > 0) {
             for (var i = 0; i < obj_paths.len; i++) {
@@ -171,30 +209,23 @@ public class Rygel.ExternalContainer : Rygel.MediaContainer {
                                         obj_path,
                                         this.host_ip,
                                         this);
-                this.media_objects.add (container);
-            }
-        }
-
-        value = all_props.lookup ("Items");
-        obj_paths = (PtrArray) value.get_boxed ();
-        if (obj_paths.len > 0) {
-            for (var i = 0; i < obj_paths.len; i++) {
-                var obj_path = (ObjectPath) obj_paths.pdata[i];
-                this.media_objects.add (new ExternalItem (obj_path,
-                                                          this));
+                this.containers.add (container);
             }
         }
 
-        this.child_count = this.media_objects.size;
+        this.child_count = this.containers.size;
+        this.props.Get (CONTAINER_IFACE, "ItemCount", out value);
+        this.child_count = value.get_int ();
     }
 
     private void on_container_updated (dynamic DBus.Object actual_container) {
-        // Re-fetch the objects
-        this.media_objects.clear ();
         try {
-            this.fetch_media_objects ();
+            // Update our information about the container
+            this.update_container ();
         } catch (GLib.Error err) {
-            warning ("Failed to re-fetch media objects: %s\n", err.message);
+            warning ("Failed to update information about container '%s': %s\n",
+                     this.id,
+                     err.message);
         }
 
         // and signal the clients
diff --git a/src/plugins/external/rygel-external-item.vala b/src/plugins/external/rygel-external-item.vala
index fe5131e..9f078e3 100644
--- a/src/plugins/external/rygel-external-item.vala
+++ b/src/plugins/external/rygel-external-item.vala
@@ -33,10 +33,26 @@ public class Rygel.ExternalItem : Rygel.MediaItem {
     private static string OBJECT_IFACE = "org.gnome.UPnP.MediaObject1";
     private static string ITEM_IFACE = "org.gnome.UPnP.MediaItem1";
 
-    public ExternalItem (string            object_path,
-                         ExternalContainer parent)
-                         throws GLib.Error {
-        base ("item:" + object_path,
+    public ExternalItem.for_path (string            object_path,
+                                  ExternalContainer parent) throws GLib.Error {
+        this ("item:" + object_path, object_path, parent);
+    }
+
+    public ExternalItem.for_id (string            id,
+                                ExternalContainer parent) throws GLib.Error {
+        var object_path = id.str ("/");
+        if (object_path == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
+
+        this (id, object_path, parent);
+    }
+
+    private ExternalItem (string            id,
+                          string            object_path,
+                          ExternalContainer parent)
+                          throws GLib.Error {
+        base (id,
               parent,
               "Unknown",        /* Title Unknown at this point */
               "Unknown");       /* UPnP Class Unknown at this point */
@@ -152,5 +168,9 @@ public class Rygel.ExternalItem : Rygel.MediaItem {
             this.color_depth = value.get_int ();
         }
     }
+
+    public static bool id_valid (string id) {
+        return id.has_prefix ("item:/");
+    }
 }
 



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