[rygel] core: Add base class for client hacks



commit 2d7ce8a4f421572f8c570c9146e774e49d655e7b
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Mon Oct 17 01:12:49 2011 +0300

    core: Add base class for client hacks
    
    A new abstract base class for client-side hacks from which XBoxHacks
    derives.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=661336

 src/rygel/Makefile.am                   |    1 +
 src/rygel/rygel-browse.vala             |    4 +-
 src/rygel/rygel-client-hacks.vala       |  106 +++++++++++++++++++++++++++++++
 src/rygel/rygel-http-get.vala           |    5 +-
 src/rygel/rygel-media-objects.vala      |    6 +-
 src/rygel/rygel-media-query-action.vala |   12 ++--
 src/rygel/rygel-search.vala             |   14 ++--
 src/rygel/rygel-xbox-hacks.vala         |   70 +++++++--------------
 8 files changed, 151 insertions(+), 67 deletions(-)
---
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index aec85e1..2ae265e 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -83,6 +83,7 @@ VAPI_SOURCE_FILES = \
 	rygel-media-query-action.vala \
 	rygel-browse.vala \
 	rygel-search.vala \
+	rygel-client-hacks.vala \
 	rygel-xbox-hacks.vala \
 	rygel-import-resource.vala \
 	rygel-item-creator.vala \
diff --git a/src/rygel/rygel-browse.vala b/src/rygel/rygel-browse.vala
index b45f5d0..2682cbf 100644
--- a/src/rygel/rygel-browse.vala
+++ b/src/rygel/rygel-browse.vala
@@ -39,8 +39,8 @@ internal class Rygel.Browse: Rygel.MediaQueryAction {
                    owned ServiceAction action) {
         base (content_dir, action);
 
-        if (this.xbox_hacks != null) {
-            this.object_id_arg = this.xbox_hacks.object_id;
+        if (this.hacks != null) {
+            this.object_id_arg = this.hacks.object_id;
         } else {
             this.object_id_arg = "ObjectID";
         }
diff --git a/src/rygel/rygel-client-hacks.vala b/src/rygel/rygel-client-hacks.vala
new file mode 100644
index 0000000..ae7c725
--- /dev/null
+++ b/src/rygel/rygel-client-hacks.vala
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2010 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *
+ * 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 Soup;
+using GUPnP;
+
+internal errordomain Rygel.ClientHacksError {
+    NA
+}
+
+internal abstract class Rygel.ClientHacks : GLib.Object {
+    private static string OBJECT_ID = "ObjectID";
+
+    public unowned string object_id { get; protected set; }
+
+    protected Regex agent_regex;
+
+    public static ClientHacks create_for_action (ServiceAction action)
+                                                 throws ClientHacksError {
+        return new XBoxHacks.for_action (action);
+    }
+
+    public static ClientHacks create_for_headers (MessageHeaders headers)
+                                                  throws ClientHacksError {
+        return new XBoxHacks.for_headers (headers);
+    }
+
+    protected ClientHacks (string agent_pattern, MessageHeaders? headers = null)
+                           throws ClientHacksError {
+        try {
+            this.agent_regex = new Regex (agent_pattern,
+                                          RegexCompileFlags.CASELESS,
+                                          0);
+        } catch (RegexError error) {
+            // This means subclasses did not provide a proper regular expression
+            assert_not_reached ();
+        }
+
+        if (headers != null) {
+            this.check_headers (headers);
+        }
+
+        this.object_id = OBJECT_ID;
+    }
+
+    public bool is_album_art_request (Soup.Message message) {
+        unowned string query = message.get_uri ().query;
+
+        if (query == null) {
+            return false;
+        }
+
+        var params = Soup.Form.decode (query);
+        var album_art = params.lookup ("albumArt");
+
+        return (album_art != null) && bool.parse (album_art);
+    }
+
+    public virtual void translate_container_id (MediaQueryAction action,
+                                                ref string       container_id) {}
+
+    public virtual void apply (MediaItem item) {}
+
+    public virtual async MediaObjects? search
+                                        (SearchableContainer container,
+                                         SearchExpression?   expression,
+                                         uint                offset,
+                                         uint                max_count,
+                                         out uint            total_matches,
+                                         Cancellable?        cancellable)
+                                         throws Error {
+        return yield container.search (expression,
+                                       offset,
+                                       max_count,
+                                       out total_matches,
+                                       cancellable);
+    }
+
+    private void check_headers (MessageHeaders headers)
+                                          throws ClientHacksError {
+        var agent = headers.get_one ("User-Agent");
+        if (agent == null || !(this.agent_regex.match (agent))) {
+            throw new ClientHacksError.NA (_("Not Applicable"));
+        }
+    }
+}
diff --git a/src/rygel/rygel-http-get.vala b/src/rygel/rygel-http-get.vala
index 0ea407c..c830483 100644
--- a/src/rygel/rygel-http-get.vala
+++ b/src/rygel/rygel-http-get.vala
@@ -84,7 +84,8 @@ internal class Rygel.HTTPGet : HTTPRequest {
         }
 
         try {
-            var hack = new XBoxHacks.for_headers (this.msg.request_headers);
+            var hack = ClientHacks.create_for_headers
+                                        (this.msg.request_headers);
             if (hack.is_album_art_request (this.msg) &&
                 this.item is VisualItem) {
                 var visual_item = this.item as VisualItem;
@@ -100,7 +101,7 @@ internal class Rygel.HTTPGet : HTTPRequest {
 
                 return;
             }
-        } catch (XBoxHacksError error) {}
+        } catch (ClientHacksError error) {}
 
         if (this.uri.thumbnail_index >= 0) {
             if (this.item is MusicItem) {
diff --git a/src/rygel/rygel-media-objects.vala b/src/rygel/rygel-media-objects.vala
index 40fb535..9cf657c 100644
--- a/src/rygel/rygel-media-objects.vala
+++ b/src/rygel/rygel-media-objects.vala
@@ -56,10 +56,10 @@ public class Rygel.MediaObjects : ArrayList<MediaObject> {
 
     internal void serialize (DIDLLiteWriter didl_writer,
                              HTTPServer     http_server,
-                             XBoxHacks?     xbox_hacks) throws Error {
+                             ClientHacks?   hacks) throws Error {
         foreach (var result in this) {
-            if (result is MediaItem && xbox_hacks != null) {
-                xbox_hacks.apply (result as MediaItem);
+            if (result is MediaItem && hacks != null) {
+                hacks.apply (result as MediaItem);
             }
 
             result.serialize (didl_writer, http_server);
diff --git a/src/rygel/rygel-media-query-action.vala b/src/rygel/rygel-media-query-action.vala
index 5a615a8..1db1236 100644
--- a/src/rygel/rygel-media-query-action.vala
+++ b/src/rygel/rygel-media-query-action.vala
@@ -49,7 +49,7 @@ internal abstract class Rygel.MediaQueryAction : GLib.Object, StateMachine {
     protected uint32 system_update_id;
     protected ServiceAction action;
     protected DIDLLiteWriter didl_writer;
-    protected XBoxHacks xbox_hacks;
+    protected ClientHacks hacks;
     protected string object_id_arg;
 
     protected MediaQueryAction (ContentDirectory    content_dir,
@@ -63,8 +63,8 @@ internal abstract class Rygel.MediaQueryAction : GLib.Object, StateMachine {
         this.didl_writer = new DIDLLiteWriter (null);
 
         try {
-            this.xbox_hacks = new XBoxHacks.for_action (this.action);
-        } catch { /* This just means we are not dealing with Xbox, yay! */ }
+            this.hacks = ClientHacks.create_for_action (this.action);
+        } catch { /* This just means we need no hacks, yay! */ }
     }
 
     public async void run () {
@@ -85,7 +85,7 @@ internal abstract class Rygel.MediaQueryAction : GLib.Object, StateMachine {
 
             results.serialize (this.didl_writer,
                                this.http_server,
-                               this.xbox_hacks);
+                               this.hacks);
 
             // Conclude the successful Browse/Search action
             this.conclude ();
@@ -132,8 +132,8 @@ internal abstract class Rygel.MediaQueryAction : GLib.Object, StateMachine {
 
         this.validate_sort_criteria ();
 
-        if (this.xbox_hacks != null) {
-            this.xbox_hacks.translate_container_id (this, ref this.object_id);
+        if (this.hacks != null) {
+            this.hacks.translate_container_id (this, ref this.object_id);
         }
     }
 
diff --git a/src/rygel/rygel-search.vala b/src/rygel/rygel-search.vala
index dd5231e..1d5e66a 100644
--- a/src/rygel/rygel-search.vala
+++ b/src/rygel/rygel-search.vala
@@ -69,13 +69,13 @@ internal class Rygel.Search:  Rygel.MediaQueryAction {
             throw parser.err;
         }
 
-        if (this.xbox_hacks != null) {
-            return yield this.xbox_hacks.search (container,
-                                                 parser.expression,
-                                                 this.index,
-                                                 this.requested_count,
-                                                 out this.total_matches,
-                                                 this.cancellable);
+        if (this.hacks != null) {
+            return yield this.hacks.search (container,
+                                            parser.expression,
+                                            this.index,
+                                            this.requested_count,
+                                            out this.total_matches,
+                                            this.cancellable);
         } else {
             return yield container.search (parser.expression,
                                            this.index,
diff --git a/src/rygel/rygel-xbox-hacks.vala b/src/rygel/rygel-xbox-hacks.vala
index 9407321..2d61326 100644
--- a/src/rygel/rygel-xbox-hacks.vala
+++ b/src/rygel/rygel-xbox-hacks.vala
@@ -24,11 +24,7 @@
 using Soup;
 using GUPnP;
 
-internal errordomain Rygel.XBoxHacksError {
-    NA
-}
-
-internal class Rygel.XBoxHacks : GLib.Object {
+internal class Rygel.XBoxHacks : ClientHacks {
     private static string AGENT =
         ".*Xbox.*|.*Allegro-Software-WebClient.*|.*SEC_HHP_Galaxy S/1\\.0.*";
     private static string DMS = "urn:schemas-upnp-org:device:MediaServer";
@@ -37,49 +33,26 @@ internal class Rygel.XBoxHacks : GLib.Object {
     private static string MODEL_NAME = "Windows Media Player Sharing";
     private static string MODEL_VERSION = "11";
     private static string CONTAINER_ID = "ContainerID";
-    private static string OBJECT_ID = "ObjectID";
 
-    public unowned string object_id { get; private set; }
+    public XBoxHacks () throws ClientHacksError {
+        base (AGENT);
+    }
 
-    public XBoxHacks.for_action (ServiceAction action) throws XBoxHacksError {
+    public XBoxHacks.for_action (ServiceAction action) throws ClientHacksError {
         unowned MessageHeaders headers = action.get_message ().request_headers;
-        this.check_headers (headers);
+        this.for_headers (headers);
     }
 
     public XBoxHacks.for_headers (MessageHeaders headers)
-                                  throws XBoxHacksError {
-        this.check_headers (headers);
-    }
+                                  throws ClientHacksError {
+        base (AGENT, headers);
 
-    private void check_headers (MessageHeaders headers) throws XBoxHacksError {
         var agent = headers.get_one ("User-Agent");
-        if (agent == null ||
-            !(agent.contains ("Xbox")) &&
-            !(agent.contains ("Allegro-Software-WebClient")) &&
-            !(agent.contains ("SEC_HHP_Galaxy S/1.0"))) {
-            throw new XBoxHacksError.NA (_("Not Applicable"));
-        }
-
         if (agent.contains ("Xbox")) {
             this.object_id = CONTAINER_ID;
-        } else {
-            this.object_id = OBJECT_ID;
         }
     }
 
-    public bool is_album_art_request (Soup.Message message) {
-        unowned string query = message.get_uri ().query;
-
-        if (query == null) {
-            return false;
-        }
-
-        var params = Soup.Form.decode (query);
-        var album_art = params.lookup ("albumArt");
-
-        return (album_art != null) && bool.parse (album_art);
-    }
-
     public void apply_on_device (RootDevice device,
                                  string     template_path) throws Error {
         if (!device.get_device_type ().has_prefix (DMS)) {
@@ -92,13 +65,15 @@ internal class Rygel.XBoxHacks : GLib.Object {
         var desc_path = template_path.replace (".xml", "-xbox.xml");
         this.save_modified_desc (doc, desc_path);
 
-        var regex = new Regex (AGENT, RegexCompileFlags.CASELESS, 0);
         var server_path = "/" + device.get_relative_location ();
-        device.context.host_path_for_agent (desc_path, server_path, regex);
+        device.context.host_path_for_agent (desc_path,
+                                            server_path,
+                                            this.agent_regex);
     }
 
-    public void translate_container_id (MediaQueryAction action,
-                                        ref string       container_id) {
+    public override void translate_container_id
+                                        (MediaQueryAction action,
+                                         ref string       container_id) {
         if (action is Search &&
             (container_id == "1" ||
              container_id == "4" ||
@@ -114,7 +89,7 @@ internal class Rygel.XBoxHacks : GLib.Object {
         }
     }
 
-    public void apply (MediaItem item) {
+    public override void apply (MediaItem item) {
         if (item.mime_type == "video/x-msvideo") {
             item.mime_type = "video/avi";
         } else if (item.mime_type == "video/mpeg") {
@@ -123,13 +98,14 @@ internal class Rygel.XBoxHacks : GLib.Object {
         }
     }
 
-    public async MediaObjects? search (SearchableContainer container,
-                                       SearchExpression?   expression,
-                                       uint                offset,
-                                       uint                max_count,
-                                       out uint            total_matches,
-                                       Cancellable?        cancellable)
-                                       throws Error {
+    public override async MediaObjects? search
+                                        (SearchableContainer container,
+                                         SearchExpression?   expression,
+                                         uint                offset,
+                                         uint                max_count,
+                                         out uint            total_matches,
+                                         Cancellable?        cancellable)
+                                         throws Error {
         var results = yield container.search (expression,
                                               offset,
                                               max_count,



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