[rygel] core: Serve special description to Xbox



commit 2ca6fe1f5b21b8559c9bbc97ceae86dc135f3a5d
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Wed Mar 31 22:22:51 2010 +0300

    core: Serve special description to Xbox

 src/rygel/rygel-root-device-factory.vala |   16 ++++--
 src/rygel/rygel-xbox-hacks.vala          |   97 ++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 5 deletions(-)
---
diff --git a/src/rygel/rygel-root-device-factory.vala b/src/rygel/rygel-root-device-factory.vala
index 9822798..d676ea6 100644
--- a/src/rygel/rygel-root-device-factory.vala
+++ b/src/rygel/rygel-root-device-factory.vala
@@ -58,11 +58,17 @@ internal class Rygel.RootDeviceFactory {
         /* Create the description xml */
         var doc = this.create_desc (plugin, desc_path, template_path);
 
-        return new RootDevice (this.context,
-                               plugin,
-                               doc,
-                               desc_path,
-                               BuildConfig.DATA_DIR);
+        var device = new RootDevice (this.context,
+                                     plugin,
+                                     doc,
+                                     desc_path,
+                                     BuildConfig.DATA_DIR);
+
+        /* Now apply the Xbox hacks */
+        var xbox_hacks = new XBoxHacks ();
+        xbox_hacks.apply_on_device (device, desc_path);
+
+        return device;
     }
 
     private XMLDoc create_desc (Plugin plugin,
diff --git a/src/rygel/rygel-xbox-hacks.vala b/src/rygel/rygel-xbox-hacks.vala
index 4be42cc..10d07c2 100644
--- a/src/rygel/rygel-xbox-hacks.vala
+++ b/src/rygel/rygel-xbox-hacks.vala
@@ -23,12 +23,20 @@
 
 using Soup;
 using GUPnP;
+using CStuff;
 
 internal errordomain Rygel.XBoxHacksError {
     NA
 }
 
 internal class Rygel.XBoxHacks : GLib.Object {
+    private static string AGENT = ".*Xbox.*";
+    private static string DMS = "urn:schemas-upnp-org:device:MediaServer";
+    private static string DMS_V1 = DMS + ":1";
+    private static string FRIENDLY_NAME_POSTFIX =
+                                        ": 1 : Windows Media Connect";
+    private static string MODEL_NAME = "Windows Media Connect";
+
     public XBoxHacks.for_action (ServiceAction action) throws XBoxHacksError {
         var agent = action.get_message ().request_headers.get ("User-Agent");
         if (!agent.contains ("Xbox")) {
@@ -36,6 +44,23 @@ internal class Rygel.XBoxHacks : GLib.Object {
         }
     }
 
+    public void apply_on_device (RootDevice device,
+                                 string     template_path) throws Error {
+        if (!device.get_device_type ().has_prefix (DMS)) {
+            return;
+        }
+
+        var doc = new XMLDoc.from_path (template_path);
+        this.modify_dms_desc (doc.doc);
+
+        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);
+    }
+
     public void translate_container_id (ref string container_id) {
         if (container_id == "1" ||
             container_id == "4" ||
@@ -54,4 +79,76 @@ internal class Rygel.XBoxHacks : GLib.Object {
             item.mime_type = "invalid/content";
         }
     }
+
+    private void modify_dms_desc (Xml.Doc doc) {
+        var element = Utils.get_xml_element ((Xml.Node *) doc,
+                                             "root",
+                                             "device",
+                                             "deviceType");
+        assert (element != null);
+        element->set_content (DMS_V1);
+
+        element = Utils.get_xml_element ((Xml.Node *) doc,
+                                         "root",
+                                         "device",
+                                         "modelName");
+        assert (element != null);
+        element->set_content (MODEL_NAME);
+
+        element = Utils.get_xml_element ((Xml.Node *) doc,
+                                         "root",
+                                         "device",
+                                         "friendlyName");
+        assert (element != null);
+        element->add_content (FRIENDLY_NAME_POSTFIX);
+
+        element = this.find_cds_type_node (doc);
+        assert (element != null);
+        element->set_content (ContentDirectory.UPNP_TYPE_V1);
+    }
+
+    private Xml.Node * find_cds_type_node (Xml.Node *doc_node) {
+        var element = Utils.get_xml_element (doc_node,
+                                             "root",
+                                             "device",
+                                             "serviceList");
+        assert (element != null && element->children != null);
+
+        Xml.Node *cds_type_node = null;
+
+        for (var service_node = element->children;
+             service_node != null;
+             service_node = service_node->next) {
+            for (var type_node = service_node->children;
+                 type_node != null;
+                 type_node = type_node->next) {
+                if (type_node->name == "serviceType" &&
+                    type_node->get_content () == ContentDirectory.UPNP_TYPE) {
+                    cds_type_node = type_node;
+                }
+            }
+
+            if (cds_type_node != null) {
+                break;
+            }
+        }
+
+        return cds_type_node;
+    }
+
+    private void save_modified_desc (XMLDoc doc,
+                                     string desc_path) throws GLib.Error {
+        FileStream f = FileStream.open (desc_path, "w+");
+        int res = -1;
+
+        if (f != null)
+            res = doc.doc.dump (f);
+
+        if (f == null || res == -1) {
+            string message = "Failed to write modified description" +
+                             " to %s.\n".printf (desc_path);
+
+            throw new IOError.FAILED (message);
+        }
+    }
 }



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