rygel r531 - trunk/src/rygel



Author: zeeshanak
Date: Mon Feb  9 22:26:56 2009
New Revision: 531
URL: http://svn.gnome.org/viewvc/rygel?rev=531&view=rev

Log:
Move 'Browse' handling to a separate class.

Added:
   trunk/src/rygel/rygel-browse.vala
Modified:
   trunk/src/rygel/Makefile.am
   trunk/src/rygel/rygel-content-directory.vala

Modified: trunk/src/rygel/Makefile.am
==============================================================================
--- trunk/src/rygel/Makefile.am	(original)
+++ trunk/src/rygel/Makefile.am	Mon Feb  9 22:26:56 2009
@@ -32,6 +32,8 @@
 		rygel-main.c \
 		rygel-content-directory.h \
 		rygel-content-directory.c \
+		rygel-browse.h \
+		rygel-browse.c \
 		rygel-plugin.h \
 		rygel-plugin.c \
 		rygel-plugin-loader.h \
@@ -73,6 +75,8 @@
 		rygel-main.vala \
 		rygel-content-directory.h \
 		rygel-content-directory.c \
+		rygel-browse.h \
+		rygel-browse.c \
 		rygel-plugin.h \
 		rygel-plugin.c \
 		rygel-plugin-loader.h \
@@ -130,7 +134,8 @@
 		    rygel-plugin.vala \
 		    rygel-media-object.vala \
 		    rygel-media-container.vala \
-		    rygel-media-item.vala
+		    rygel-media-item.vala \
+		    rygel-browse.vala
 
 rygel-1.0.vapi: $(VAPI_SOURCE_FILES)
 	$(VALAC) -C --library=rygel-1.0 \

Added: trunk/src/rygel/rygel-browse.vala
==============================================================================
--- (empty file)
+++ trunk/src/rygel/rygel-browse.vala	Mon Feb  9 22:26:56 2009
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
+ * Copyright (C) 2007 OpenedHand Ltd.
+ *
+ * Author: Zeeshan Ali <zeenix gmail com>
+ *         Jorn Baayen <jorn openedhand 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 Rygel;
+using GUPnP;
+using Gee;
+
+/**
+ * Browse action implementation.
+ */
+public class Browse: GLib.Object {
+    public const int MAX_REQUESTED_COUNT = 128;
+
+    // In arguments
+    public string object_id;
+    public string browse_flag;
+    public string filter;
+    public uint   index;           // Starting index
+    public uint   requested_count;
+    public string sort_criteria;
+
+    // Out arguments
+    public uint number_returned;
+    public uint total_matches;
+    public uint update_id;
+
+    private unowned ContentDirectory content_dir;
+    private ServiceAction action;
+    private DIDLLiteWriter didl_writer;
+
+    // Signals
+    public signal void completed ();
+
+    public Browse (ContentDirectory    content_dir,
+                   owned ServiceAction action) {
+        this.content_dir = content_dir;
+        this.action = (owned) action;
+
+        this.didl_writer = new DIDLLiteWriter ();
+    }
+
+    public void start () {
+        /* Start DIDL-Lite fragment */
+        this.didl_writer.start_didl_lite (null, null, true);
+
+        /* Handle incoming arguments */
+        bool metadata = this.parse_args ();
+        if (metadata) {
+            // BrowseMetadata
+            this.handle_metadata_request ();
+        } else {
+            // BrowseDirectChildren
+            this.handle_children_request ();
+        }
+    }
+
+    private void handle_metadata_request () {
+        MediaObject media_object;
+
+        try {
+            media_object = this.content_dir.find_object_by_id (this.object_id);
+
+            media_object.serialize (didl_writer);
+        } catch (Error err) {
+            this.handle_error (err);
+            return;
+        }
+
+        if (media_object is MediaContainer) {
+            this.update_id = ((MediaContainer) media_object).update_id;
+        } else {
+            this.update_id = uint32.MAX;
+        }
+
+        this.number_returned = 1;
+        this.total_matches = 1;
+
+        // Conclude the successful Browse action
+        this.conclude ();
+    }
+
+    private void handle_children_request () {
+        if (this.requested_count == 0)
+            this.requested_count = MAX_REQUESTED_COUNT;
+
+        MediaObject media_object;
+        try {
+            media_object = this.content_dir.find_object_by_id (this.object_id);
+        } catch (Error err) {
+            this.handle_error (err);
+            return;
+        }
+
+        if (!(media_object is MediaContainer)) {
+            this.handle_error (
+                new ContentDirectoryError.NO_SUCH_OBJECT ("No such object"));
+            return;
+        }
+
+        var container = (MediaContainer) media_object;
+        this.total_matches = container.child_count;
+        if (this.requested_count == 0) {
+            // No max count requested, try to fetch all children
+            this.requested_count = this.total_matches;
+        }
+
+        var children = container.get_children (this.index,
+                                               this.requested_count);
+        if (children == null) {
+            this.handle_error (
+                new ContentDirectoryError.NO_SUCH_OBJECT ("No such object"));
+            return;
+        }
+
+        /* serialize all children */
+        for (int i = 0; i < children.size; i++) {
+            try {
+                children[i].serialize (didl_writer);
+            } catch (Error err) {
+                this.handle_error (err);
+                return;
+            }
+        }
+
+        this.update_id = ((MediaContainer) media_object).update_id;
+        this.number_returned = children.size;
+
+        // Conclude the successful Browse action
+        this.conclude ();
+    }
+
+    private bool parse_args () {
+        this.action.get ("ObjectID", typeof (string), out this.object_id,
+                    "BrowseFlag", typeof (string), out this.browse_flag,
+                    "Filter", typeof (string), out this.filter,
+                    "StartingIndex", typeof (uint), out this.index,
+                    "RequestedCount", typeof (uint), out this.requested_count,
+                    "SortCriteria", typeof (string), out this.sort_criteria);
+
+        /* BrowseFlag */
+        bool metadata = false;
+        if (this.browse_flag != null &&
+            this.browse_flag == "BrowseDirectChildren") {
+            metadata = false;
+        } else if (this.browse_flag != null &&
+                   this.browse_flag == "BrowseMetadata") {
+            metadata = true;
+        } else {
+            this.handle_error (
+                    new ContentDirectoryError.INVALID_ARGS ("Invalid Args"));
+        }
+
+        /* ObjectID */
+        if (this.object_id == null) {
+            /* Stupid Xbox */
+            this.action.get ("ContainerID",
+                             typeof (string),
+                             out this.object_id);
+        }
+
+        if (this.object_id == null) {
+            // Sorry we can't do anything without ObjectID
+            this.handle_error (
+                new ContentDirectoryError.NO_SUCH_OBJECT ("No such object"));
+        }
+
+        return metadata;
+    }
+
+    private void conclude () {
+        /* End DIDL-Lite fragment */
+        this.didl_writer.end_didl_lite ();
+
+        /* Retrieve generated string */
+        string didl = this.didl_writer.get_string ();
+
+        if (this.update_id == uint32.MAX) {
+            this.update_id = this.content_dir.root_container.update_id;
+        }
+
+        /* Set action return arguments */
+        this.action.set ("Result", typeof (string), didl,
+                         "NumberReturned", typeof (uint), this.number_returned,
+                         "TotalMatches", typeof (uint), this.total_matches,
+                         "UpdateID", typeof (uint), this.update_id);
+
+        this.action.return ();
+        this.completed ();
+    }
+
+    private void handle_error (Error error) {
+        if (error is ContentDirectoryError) {
+            warning ("Failed to browse '%s': %s\n",
+                     this.object_id,
+                     error.message);
+            this.action.return_error (error.code, error.message);
+        } else {
+            warning ("Failed to browse '%s': %s\n",
+                     this.object_id,
+                     error.message);
+            this.action.return_error (701, error.message);
+        }
+
+        this.completed ();
+    }
+}
+

Modified: trunk/src/rygel/rygel-content-directory.vala
==============================================================================
--- trunk/src/rygel/rygel-content-directory.vala	(original)
+++ trunk/src/rygel/rygel-content-directory.vala	Mon Feb  9 22:26:56 2009
@@ -33,21 +33,6 @@
     INVALID_ARGS = 402
 }
 
-public class BrowseArgs {
-    // In arguments
-    public string object_id;
-    public string browse_flag;
-    public string filter;
-    public uint   index;           // Starting index
-    public uint   requested_count;
-    public string sort_criteria;
-
-    // Out arguments
-    public uint   number_returned;
-    public uint   total_matches;
-    public uint   update_id;
-}
-
 /**
  * Basic implementation of UPnP ContentDirectory service version 2. Most often
  * plugins will provide a child of this class. The inheriting classes should
@@ -59,17 +44,15 @@
                     "urn:schemas-upnp-org:service:ContentDirectory:2";
     public const string DESCRIPTION_PATH = "xml/ContentDirectory.xml";
 
-    public const int MAX_REQUESTED_COUNT = 128;
-
     protected string feature_list;
     protected string search_caps;
     protected string sort_caps;
 
     protected HTTPServer http_server;
 
-    protected MediaContainer root_container;
+    public MediaContainer root_container;
 
-    DIDLLiteWriter didl_writer;
+    private ArrayList<Browse> browses;
 
     // Public abstract methods derived classes need to implement
     public virtual MediaContainer? create_root_container () {
@@ -77,10 +60,11 @@
     }
 
     public override void constructed () {
-        this.didl_writer = new DIDLLiteWriter ();
         this.http_server = new HTTPServer (context, this.get_type ().name ());
         this.root_container = this.create_root_container ();
 
+        this.browses = new ArrayList<Browse> ();
+
         this.http_server.item_requested += this.on_item_requested;
 
         this.feature_list =
@@ -121,50 +105,28 @@
         this.http_server.destroy ();
     }
 
-    /* Browse action implementation */
-    protected virtual void browse_cb (ContentDirectory    content_dir,
-                                      owned ServiceAction action) {
-        bool metadata;
-
-        BrowseArgs args = new BrowseArgs ();
-
-        /* Start DIDL-Lite fragment */
-        this.didl_writer.start_didl_lite (null, null, true);
-
-        try {
-            /* Handle incoming arguments */
-            metadata = this.parse_browse_args (action, args);
+    public MediaObject find_object_by_id (string object_id) throws GLib.Error {
+        if (object_id == this.root_container.id) {
+            return this.root_container;
+        }
 
-            if (metadata) {
-                // BrowseMetadata
-                this.browse_metadata (args);
-            } else {
-                // BrowseDirectChildren
-                this.browse_direct_children (args);
-            }
+        var media_object = this.root_container.find_object_by_id (object_id);
+        if (media_object == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
 
-            /* End DIDL-Lite fragment */
-            this.didl_writer.end_didl_lite ();
+        return media_object;
+    }
 
-            /* Retrieve generated string */
-            string didl = this.didl_writer.get_string ();
+    /* Browse action implementation */
+    protected virtual void browse_cb (ContentDirectory    content_dir,
+                                      owned ServiceAction action) {
+        Browse browse = new Browse (this, action);
 
-            // Conclude the successful Browse action
-            conclude_browse (action, didl, args);
-        } catch (ContentDirectoryError error) {
-            warning ("Failed to browse '%s': %s\n",
-                     args.object_id,
-                     error.message);
-            action.return_error (error.code, error.message);
-        } catch (Error error) {
-            warning ("Failed to browse '%s': %s\n",
-                     args.object_id,
-                     error.message);
-            action.return_error (701, error.message);
-        }
+        this.browses.add (browse);
+        browse.completed += this.on_browse_completed;
 
-        /* Reset the parser state */
-        this.didl_writer.reset ();
+        browse.start ();
     }
 
     /* GetSystemUpdateID action implementation */
@@ -239,130 +201,8 @@
         value.set_string (this.feature_list);
     }
 
-    private void browse_metadata (BrowseArgs args) throws Error {
-        MediaObject media_object = this.find_object_by_id (args.object_id);
-
-        media_object.serialize (didl_writer);
-
-        if (media_object is MediaContainer) {
-            args.update_id = ((MediaContainer) media_object).update_id;
-        } else {
-            args.update_id = uint32.MAX;
-        }
-
-        args.number_returned = 1;
-        args.total_matches = 1;
-    }
-
-    private void browse_direct_children (BrowseArgs args) throws Error {
-        if (args.requested_count == 0)
-            args.requested_count = MAX_REQUESTED_COUNT;
-
-        Gee.List<MediaObject> children;
-
-        children = this.get_children (args.object_id,
-                                      args.index,
-                                      args.requested_count,
-                                      out args.total_matches,
-                                      out args.update_id);
-        /* Iterate through all items */
-        for (int i = 0; i < children.size; i++) {
-            children[i].serialize (didl_writer);
-        }
-
-        args.number_returned = children.size;
-    }
-
-    private bool parse_browse_args (ServiceAction action,
-                                    BrowseArgs args) throws Error {
-        action.get ("ObjectID", typeof (string), out args.object_id,
-                    "BrowseFlag", typeof (string), out args.browse_flag,
-                    "Filter", typeof (string), out args.filter,
-                    "StartingIndex", typeof (uint), out args.index,
-                    "RequestedCount", typeof (uint), out args.requested_count,
-                    "SortCriteria", typeof (string), out args.sort_criteria);
-
-        /* BrowseFlag */
-        bool metadata;
-        if (args.browse_flag != null &&
-            args.browse_flag == "BrowseDirectChildren") {
-            metadata = false;
-        } else if (args.browse_flag != null &&
-                   args.browse_flag == "BrowseMetadata") {
-            metadata = true;
-        } else {
-            throw new ContentDirectoryError.INVALID_ARGS ("Invalid Args");
-        }
-
-        /* ObjectID */
-        if (args.object_id == null) {
-            /* Stupid Xbox */
-            action.get ("ContainerID", typeof (string), out args.object_id);
-        }
-
-        if (args.object_id == null) {
-            // Sorry we can't do anything without ObjectID
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        return metadata;
-    }
-
-    private void conclude_browse (ServiceAction action,
-                                  string        didl,
-                                  BrowseArgs    args) {
-        if (args.update_id == uint32.MAX) {
-            args.update_id = this.root_container.update_id;
-        }
-
-        /* Set action return arguments */
-        action.set ("Result", typeof (string), didl,
-                    "NumberReturned", typeof (uint), args.number_returned,
-                    "TotalMatches", typeof (uint), args.total_matches,
-                    "UpdateID", typeof (uint), args.update_id);
-
-        action.return ();
-    }
-
-    private Gee.List<MediaObject> get_children (string   container_id,
-                                                uint     offset,
-                                                uint     max_count,
-                                                out uint child_count,
-                                                out uint update_id)
-                                                throws GLib.Error {
-        var media_object = this.find_object_by_id (container_id);
-        if (!(media_object is MediaContainer)) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        var container = (MediaContainer) media_object;
-        child_count = container.child_count;
-        if (max_count == 0) {
-            // No max count requested, try to fetch all children
-            max_count = child_count;
-        }
-
-        var children = container.get_children (offset, max_count);
-        if (children == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        update_id = ((MediaContainer) media_object).update_id;
-
-        return children;
-    }
-
-    private MediaObject find_object_by_id (string object_id) throws GLib.Error {
-        if (object_id == this.root_container.id) {
-            return this.root_container;
-        }
-
-        var media_object = this.root_container.find_object_by_id (object_id);
-        if (media_object == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        return media_object;
+    private void on_browse_completed (Browse browse) {
+        this.browses.remove (browse);
     }
 
     private void on_item_requested (HTTPServer    http_server,



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