[rygel] core: Refactor Search and Browse



commit 67809c2296e8d14a899b340509c28edf916d0491
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Wed Jul 21 17:22:29 2010 +0300

    core: Refactor Search and Browse
    
    Move common code/logic between Search and Browse into a separate base
    class: MediaQueryAction.

 po/POTFILES.in                          |    1 +
 src/rygel/Makefile.am                   |    1 +
 src/rygel/rygel-browse.vala             |  164 +++-----------------------
 src/rygel/rygel-media-query-action.vala |  197 +++++++++++++++++++++++++++++++
 src/rygel/rygel-search.vala             |  149 +++---------------------
 5 files changed, 231 insertions(+), 281 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0891c9c..7e33929 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -75,6 +75,7 @@ src/plugins/tracker/rygel-tracker-tags.vala
 src/plugins/tracker/rygel-tracker-video-item-factory.vala
 src/plugins/tracker/rygel-tracker-videos.vala
 src/plugins/tracker/rygel-tracker-years.vala
+src/rygel/rygel-media-query-action.vala
 src/rygel/rygel-browse.vala
 src/rygel/rygel-cmdline-config.vala
 src/rygel/rygel-configuration.vala
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index 87a3633..9978ed3 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -78,6 +78,7 @@ VAPI_SOURCE_FILES = rygel-configuration.vala \
 			rygel-media-art-store.vala \
 		    rygel-subtitle.vala \
 		    rygel-subtitle-manager.vala \
+		    rygel-media-query-action.vala \
 		    rygel-browse.vala \
 		    rygel-search.vala \
 			rygel-xbox-hacks.vala \
diff --git a/src/rygel/rygel-browse.vala b/src/rygel/rygel-browse.vala
index 33c9ab5..b89b428 100644
--- a/src/rygel/rygel-browse.vala
+++ b/src/rygel/rygel-browse.vala
@@ -31,83 +31,22 @@ using Soup;
  * associated with the Browse action handling that exists to make asynchronous
  * handling of Browse action possible.
  */
-internal class Rygel.Browse: GLib.Object, Rygel.StateMachine {
-    // 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;
-
+internal class Rygel.Browse: Rygel.MediaQueryAction {
     // The media object corresponding to object_id
     private bool fetch_metadata;
 
-    private MediaContainer root_container;
-    private uint32 system_update_id;
-    private ServiceAction action;
-    private Rygel.DIDLLiteWriter didl_writer;
-    private XBoxHacks xbox_hacks;
-
-    public Cancellable cancellable { get; set; }
-
     public Browse (ContentDirectory    content_dir,
                    owned ServiceAction action) {
-        this.root_container = content_dir.root_container;
-        this.system_update_id = content_dir.system_update_id;
-        this.cancellable = content_dir.cancellable;
-        this.action = (owned) action;
-
-        this.didl_writer = new Rygel.DIDLLiteWriter (content_dir.http_server);
-
-        try {
-            this.xbox_hacks = new XBoxHacks.for_action (this.action);
-        } catch { /* This just means we are not dealing with Xbox, yay! */ }
+        base (content_dir,
+              action,
+              "ObjectID",
+              _("Failed to browse '%s': %s\n"));
     }
 
-    public async void run () {
-        try {
-            this.parse_args ();
-
-            var media_object = yield this.fetch_media_object ();
-
-            Gee.List<MediaObject> results;
-            if (this.fetch_metadata) {
-                // BrowseMetadata
-                results = this.handle_metadata_request (media_object);
-            } else {
-                // BrowseDirectChildren
-                results = yield this.handle_children_request (media_object);
-            }
-
-            foreach (var result in results) {
-                if (result is MediaItem && this.xbox_hacks != null) {
-                    this.xbox_hacks.apply (result as MediaItem);
-                }
-
-                this.didl_writer.serialize (result);
-            }
-
-            // Conclude the successful Browse action
-            this.conclude ();
-        } catch (Error err) {
-            this.handle_error (err);
-        }
-    }
+    protected override void parse_args () throws Error {
+        base.parse_args ();
 
-    private async void parse_args () throws Error {
-        /* Start by parsing the 'in' arguments */
-        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);
+        this.action.get ("BrowseFlag", typeof (string), out this.browse_flag);
 
         /* BrowseFlag */
         if (this.browse_flag != null &&
@@ -120,56 +59,22 @@ internal class Rygel.Browse: GLib.Object, Rygel.StateMachine {
             throw new ContentDirectoryError.INVALID_ARGS (
                                         _("Invalid Arguments"));
         }
-
-        /* ObjectID */
-        if (this.object_id == null) {
-            /* Stupid Xbox */
-            this.action.get ("ContainerID",
-                             typeof (string),
-                             out this.object_id);
-            // Map some special browse requests to browse on the root folder
-            if (this.object_id == "15" ||
-                this.object_id == "14" ||
-                this.object_id == "16") {
-                this.object_id = "0";
-            }
-        }
-
-        if (this.object_id == null) {
-            // Sorry we can't do anything without ObjectID
-            throw new ContentDirectoryError.NO_SUCH_OBJECT (
-                                        _("No such object"));
-        }
     }
 
-    private async MediaObject fetch_media_object () throws Error {
-        if (this.object_id == this.root_container.id) {
-            return this.root_container;
+    protected override async Gee.List<MediaObject> fetch_results (
+                                        MediaObject media_object) throws Error {
+        if (this.fetch_metadata) {
+            // BrowseMetadata
+            return this.handle_metadata_request (media_object);
         } else {
-            debug ("searching for object '%s'..", this.object_id);
-            var media_object = yield this.root_container.find_object (
-                                        this.object_id,
-                                        this.cancellable);
-            if (media_object == null) {
-                throw new ContentDirectoryError.NO_SUCH_OBJECT (
-                                        _("No such object"));
-            }
-            debug ("object '%s' found.", this.object_id);
-
-            return media_object;
+            // BrowseDirectChildren
+            return yield this.handle_children_request (media_object);
         }
     }
 
     private Gee.List<MediaObject> handle_metadata_request (
                                         MediaObject media_object)
                                         throws Error {
-        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;
 
         var results = new ArrayList<MediaObject> ();
@@ -188,7 +93,6 @@ internal class Rygel.Browse: GLib.Object, Rygel.StateMachine {
 
         var container = (MediaContainer) media_object;
         this.total_matches = container.child_count;
-        this.update_id = container.update_id;
 
         if (this.requested_count == 0) {
             // No max count requested, try to fetch all children
@@ -202,7 +106,6 @@ internal class Rygel.Browse: GLib.Object, Rygel.StateMachine {
         var children = yield container.get_children (this.index,
                                                      this.requested_count,
                                                      this.cancellable);
-        this.number_returned = children.size;
         debug ("Fetched %u children of container '%s' from index %u.",
                this.requested_count,
                this.object_id,
@@ -210,42 +113,5 @@ internal class Rygel.Browse: GLib.Object, Rygel.StateMachine {
 
         return children;
     }
-
-    private void conclude () {
-        // Apply the filter from the client
-        this.didl_writer.filter (this.filter);
-
-        /* Retrieve generated string */
-        string didl = this.didl_writer.get_string ();
-
-        if (this.update_id == uint32.MAX) {
-            this.update_id = this.system_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 ();
-    }
 }
 
diff --git a/src/rygel/rygel-media-query-action.vala b/src/rygel/rygel-media-query-action.vala
new file mode 100644
index 0000000..266950c
--- /dev/null
+++ b/src/rygel/rygel-media-query-action.vala
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali <zeenix gmail 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;
+
+/**
+ * Base class of Browse and Search actions.
+ */
+internal abstract class Rygel.MediaQueryAction : GLib.Object, StateMachine {
+    // 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;
+
+    public Cancellable cancellable { get; set; }
+
+    protected MediaContainer root_container;
+    protected uint32 system_update_id;
+    protected ServiceAction action;
+    protected Rygel.DIDLLiteWriter didl_writer;
+    protected XBoxHacks xbox_hacks;
+
+    private string object_id_arg;
+    private string error_message;
+
+    protected MediaQueryAction (ContentDirectory    content_dir,
+                                owned ServiceAction action,
+                                string              object_id_arg,
+                                string              error_message) {
+        this.root_container = content_dir.root_container;
+        this.system_update_id = content_dir.system_update_id;
+        this.cancellable = content_dir.cancellable;
+        this.action = (owned) action;
+        this.object_id_arg = object_id_arg;
+        this.error_message = error_message;
+
+        this.didl_writer = new Rygel.DIDLLiteWriter (content_dir.http_server);
+
+        try {
+            this.xbox_hacks = new XBoxHacks.for_action (this.action);
+        } catch { /* This just means we are not dealing with Xbox, yay! */ }
+    }
+
+    public async void run () {
+        try {
+            this.parse_args ();
+
+            var media_object = yield this.fetch_media_object ();
+            var results = yield this.fetch_results (media_object);
+
+            this.number_returned = results.size;
+            if (media_object is MediaContainer) {
+                this.update_id = ((MediaContainer) media_object).update_id;
+            } else {
+                this.update_id = uint32.MAX;
+            }
+
+            foreach (var result in results) {
+                if (result is MediaItem && this.xbox_hacks != null) {
+                    this.xbox_hacks.apply (result as MediaItem);
+                }
+
+                this.didl_writer.serialize (result);
+            }
+
+            // Conclude the successful Browse/Search action
+            this.conclude ();
+        } catch (Error err) {
+            this.handle_error (err);
+        }
+    }
+
+    protected virtual void parse_args () throws Error {
+        this.action.get (this.object_id_arg,
+                             typeof (string),
+                             out this.object_id,
+                         "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);
+
+        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
+            throw new ContentDirectoryError.NO_SUCH_OBJECT (
+                                        _("No such object"));
+        }
+
+        if (this.xbox_hacks != null) {
+            this.xbox_hacks.translate_container_id (ref this.object_id);
+        }
+    }
+
+    protected abstract async Gee.List<MediaObject> fetch_results (
+                                        MediaObject media_object) throws Error;
+
+    private async MediaObject fetch_media_object () throws Error {
+        if (this.object_id == this.root_container.id) {
+            return this.root_container;
+        } else {
+            debug ("searching for object '%s'..", this.object_id);
+            var media_object = yield this.root_container.find_object (
+                                        this.object_id,
+                                        this.cancellable);
+            if (media_object == null) {
+                throw new ContentDirectoryError.NO_SUCH_OBJECT (
+                                        _("No such object"));
+            }
+            debug ("object '%s' found.", this.object_id);
+
+            return media_object;
+        }
+    }
+
+    private void conclude () {
+        // Apply the filter from the client
+        this.didl_writer.filter (this.filter);
+
+        /* Retrieve generated string */
+        string didl = this.didl_writer.get_string ();
+
+        if (this.update_id == uint32.MAX) {
+            this.update_id = this.system_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) {
+        warning (this.error_message, this.object_id, error.message);
+
+        if (error is ContentDirectoryError) {
+            this.action.return_error (error.code, error.message);
+        } else {
+            this.action.return_error (701, error.message);
+        }
+
+        this.completed ();
+    }
+}
diff --git a/src/rygel/rygel-search.vala b/src/rygel/rygel-search.vala
index 10eeae8..e05b780 100644
--- a/src/rygel/rygel-search.vala
+++ b/src/rygel/rygel-search.vala
@@ -28,114 +28,36 @@ using Soup;
 /**
  * Search action implementation.
  */
-internal class Rygel.Search: GLib.Object, Rygel.StateMachine {
+internal class Rygel.Search:  Rygel.MediaQueryAction {
     // In arguments
-    public string container_id;
     public string search_criteria;
-    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 MediaContainer root_container;
-    private uint32 system_update_id;
-    private ServiceAction action;
-    private Rygel.DIDLLiteWriter didl_writer;
-    private XBoxHacks xbox_hacks;
-
-    public Cancellable cancellable { get; set; }
 
     public Search (ContentDirectory    content_dir,
                    owned ServiceAction action) {
-        this.root_container = content_dir.root_container;
-        this.system_update_id = content_dir.system_update_id;
-        this.cancellable = content_dir.cancellable;
-        this.action = (owned) action;
-
-        this.didl_writer = new Rygel.DIDLLiteWriter (content_dir.http_server);
-
-        try {
-            this.xbox_hacks = new XBoxHacks.for_action (this.action);
-        } catch { /* This just means we are not dealing with Xbox, yay! */ }
+        base (content_dir,
+              action,
+              "ContainerID",
+              _("Failed to search in '%s': %s"));
     }
 
-    public async void run () {
-        // Start by parsing the 'in' arguments
-        this.action.get ("ContainerID",
-                            typeof (string),
-                            out this.container_id,
-                         "SearchCriteria",
-                            typeof (string),
-                            out this.search_criteria,
-                         "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);
+    protected override void parse_args () throws Error {
+        base.parse_args ();
 
-        try {
-            if (this.container_id == null || this.search_criteria == null) {
-                // Sorry we can't do anything without these two parameters
-                throw new ContentDirectoryError.NO_SUCH_OBJECT (
-                                        _("No such container"));
-            }
-
-            debug (_("Executing search request: %s"), this.search_criteria);
-
-            if (this.xbox_hacks != null) {
-                this.xbox_hacks.translate_container_id (ref this.container_id);
-            }
-
-            var container = yield this.fetch_container ();
-            var results = yield this.fetch_results (container);
-
-            // Serialize results
-            foreach (var result in results) {
-                if (result is MediaItem && this.xbox_hacks != null) {
-                    this.xbox_hacks.apply (result as MediaItem);
-                }
-
-                this.didl_writer.serialize (result);
-            }
-
-            this.conclude ();
-        } catch (Error err) {
-            this.handle_error (err);
-        }
-    }
-
-    private async MediaContainer fetch_container () throws Error {
-        if (this.container_id == this.root_container.id) {
-            return this.root_container;
-        }
+        this.action.get ("SearchCriteria",
+                            typeof (string),
+                            out this.search_criteria);
 
-        var media_object = yield this.root_container.find_object (
-                                        this.container_id,
-                                        this.cancellable);
-        if (media_object == null || !(media_object is MediaContainer)) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT (
-                    _("Specified container does not exist."));
+        if (this.search_criteria == null) {
+            throw new ContentDirectoryError.INVALID_ARGS (
+                                        "No search criteria given");
         }
 
-        return media_object as MediaContainer;
+        debug (_("Executing search request: %s"), this.search_criteria);
     }
 
-    private async Gee.List<MediaObject> fetch_results (
-                                        MediaContainer container)
-                                        throws Error {
-        this.update_id = container.update_id;
+    protected override async Gee.List<MediaObject> fetch_results (
+                                        MediaObject media_object) throws Error {
+        var container = media_object as MediaContainer;
 
         var parser = new Rygel.SearchCriteriaParser (this.search_criteria);
         yield parser.run ();
@@ -155,44 +77,7 @@ internal class Rygel.Search: GLib.Object, Rygel.StateMachine {
             throw new ContentDirectoryError.CANT_PROCESS (message);
         }
 
-        this.number_returned = results.size;
-
         return results;
     }
-
-    private void conclude () {
-        // Apply the filter from the client
-        this.didl_writer.filter (this.filter);
-
-        // Retrieve generated string
-        string didl = this.didl_writer.get_string ();
-
-        if (this.update_id == uint32.MAX) {
-            this.update_id = this.system_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) {
-        warning (_("Failed to search in '%s': %s"),
-                 this.container_id,
-                 error.message);
-
-        if (error is ContentDirectoryError) {
-            this.action.return_error (error.code, error.message);
-        } else {
-            this.action.return_error (701, error.message);
-        }
-
-        this.completed ();
-    }
 }
 



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