[rygel] core,plugins: Add server capabilities



commit c8057e923b88e323f4c3d533739b7bf73b652538
Author: Jens Georg <jensg openismus com>
Date:   Thu Oct 11 12:25:30 2012 +0200

    core,plugins: Add server capabilities
    
    Fixes:
        https://bugzilla.gnome.org/show_bug.cgi?id=676024

 data/xml/ContentDirectory-NoTrack.xml.in           |  372 ++++++++++++++++++++
 data/xml/Makefile.am                               |    1 +
 examples/standalone-server.c                       |    4 +-
 src/librygel-core/rygel-description-file.vala      |   59 +++-
 src/librygel-core/rygel-plugin.vala                |   33 ++-
 src/librygel-core/rygel-root-device-factory.vala   |   26 +--
 .../rygel-media-renderer-plugin.vala               |    6 +-
 src/librygel-renderer/rygel-media-renderer.vala    |   12 +-
 src/librygel-server/rygel-content-directory.vala   |    2 +
 src/librygel-server/rygel-media-server-plugin.vala |   14 +-
 src/librygel-server/rygel-media-server.vala        |   12 +-
 .../media-export/rygel-media-export-plugin.vala    |    5 +-
 src/plugins/tracker/rygel-tracker-plugin.vala      |    2 +-
 13 files changed, 503 insertions(+), 45 deletions(-)
---
diff --git a/data/xml/ContentDirectory-NoTrack.xml.in b/data/xml/ContentDirectory-NoTrack.xml.in
new file mode 100644
index 0000000..8460158
--- /dev/null
+++ b/data/xml/ContentDirectory-NoTrack.xml.in
@@ -0,0 +1,372 @@
+<?xml version="1.0"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+   <specVersion>
+      <major>1</major>
+      <minor>0</minor>
+   </specVersion>
+   <serviceStateTable>
+      <stateVariable sendEvents="no">
+         <name>SearchCapabilities</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>SortCapabilities</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="yes">
+         <name>SystemUpdateID</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="yes">
+         <name>ContainerUpdateIDs</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>FeatureList</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_ObjectID</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_Result</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_BrowseFlag</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>BrowseMetadata</allowedValue>
+            <allowedValue>BrowseDirectChildren</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_Filter</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_SortCriteria</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_Index</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_Count</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_UpdateID</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_SearchCriteria</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_URI</name>
+         <dataType>uri</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_TransferID</name>
+         <dataType>ui4</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="yes">
+         <name>TransferIDs</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_TransferStatus</name>
+         <dataType>string</dataType>
+         <allowedValueList>
+            <allowedValue>COMPLETED</allowedValue>
+            <allowedValue>ERROR</allowedValue>
+            <allowedValue>IN_PROGRESS</allowedValue>
+            <allowedValue>STOPPED</allowedValue>
+         </allowedValueList>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_TransferLength</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>A_ARG_TYPE_TransferTotal</name>
+         <dataType>string</dataType>
+      </stateVariable>
+   </serviceStateTable>
+
+   <actionList>
+      <action>
+         <name>GetSearchCapabilities</name>
+         <argumentList>
+            <argument>
+               <name>SearchCaps</name>
+               <direction>out</direction>
+               <relatedStateVariable>SearchCapabilities</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>GetSortCapabilities</name>
+         <argumentList>
+            <argument>
+               <name>SortCaps</name>
+               <direction>out</direction>
+               <relatedStateVariable>SortCapabilities</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>GetSystemUpdateID</name>
+         <argumentList>
+            <argument>
+               <name>Id</name>
+               <direction>out</direction>
+               <relatedStateVariable>SystemUpdateID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>GetFeatureList</name>
+         <argumentList>
+            <argument>
+               <name>FeatureList</name>
+               <direction>out</direction>
+               <relatedStateVariable>FeatureList</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+
+      <action>
+         <name>Browse</name>
+         <argumentList>
+            <argument>
+               <name>ObjectID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>BrowseFlag</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Filter</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>StartingIndex</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RequestedCount</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>SortCriteria</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Result</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NumberReturned</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TotalMatches</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>UpdateID</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>Search</name>
+         <argumentList>
+            <argument>
+               <name>ContainerID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>SearchCriteria</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_SearchCriteria</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Filter</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>StartingIndex</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RequestedCount</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>SortCriteria</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Result</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NumberReturned</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TotalMatches</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>UpdateID</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>CreateObject</name>
+         <argumentList>
+            <argument>
+               <name>ContainerID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Elements</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>ObjectID</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>Result</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>DestroyObject</name>
+         <argumentList>
+            <argument>
+               <name>ObjectID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>ImportResource</name>
+         <argumentList>
+            <argument>
+               <name>SourceURI</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_URI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>DestinationURI</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_URI</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TransferID</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>GetTransferProgress</name>
+         <argumentList>
+            <argument>
+               <name>TransferID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TransferStatus</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferStatus</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TransferLength</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferLength</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TransferTotal</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferTotal</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+      <action>
+         <name>StopTransferResource</name>
+         <argumentList>
+            <argument>
+               <name>TransferID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_TransferID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+   </actionList>
+</scpd>
diff --git a/data/xml/Makefile.am b/data/xml/Makefile.am
index d35f3e4..2dcdccb 100644
--- a/data/xml/Makefile.am
+++ b/data/xml/Makefile.am
@@ -1,6 +1,7 @@
 xml_in_files = MediaServer3.xml.in \
                MediaRenderer2.xml.in \
                ContentDirectory.xml.in \
+               ContentDirectory-NoTrack.xml.in \
                ConnectionManager.xml.in \
                AVTransport2.xml.in \
                RenderingControl2.xml.in \
diff --git a/examples/standalone-server.c b/examples/standalone-server.c
index 93d7962..16846bb 100644
--- a/examples/standalone-server.c
+++ b/examples/standalone-server.c
@@ -132,7 +132,9 @@ int main (int argc, char *argv[])
         info = g_file_enumerator_next_file (enumerator, NULL, NULL);
     }
 
-    server = rygel_media_server_new ("LibRygel sample server", root_container);
+    server = rygel_media_server_new ("LibRygel sample server",
+                                     root_container,
+                                     RYGEL_PLUGIN_CAPABILITIES_NONE);
     rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (server), "eth0");
     rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (server), "wlan0");
 
diff --git a/src/librygel-core/rygel-description-file.vala b/src/librygel-core/rygel-description-file.vala
index 025f133..2d59d83 100644
--- a/src/librygel-core/rygel-description-file.vala
+++ b/src/librygel-core/rygel-description-file.vala
@@ -120,6 +120,59 @@ public class Rygel.DescriptionFile : Object {
     }
 
     /**
+     * Set the DLNA caps of this root device and while taking the
+     * capabilities of the plugin into account.
+     *
+     * @param capabilities RygelPluginCapabilities flags
+     */
+    public void set_dlna_caps (PluginCapabilities capabilities) {
+        var flags = new string[0];
+        var content = "";
+
+        if ((PluginCapabilities.UPLOAD & capabilities) != 0) {
+            // This means "Supports upload to AnyContainer_DLNA.ORG", but we
+            // also use it as "supports upload". AnyContainer upload is
+            // handled by Rygel transparently.
+            var allow_upload = true;
+            var allow_delete = false;
+
+            try {
+                var config = MetaConfig.get_default ();
+                allow_upload = config.get_allow_upload ();
+                allow_delete = config.get_allow_deletion ();
+            } catch (GLib.Error error) { }
+
+            if (allow_upload) {
+                if (PluginCapabilities.IMAGE_UPLOAD in capabilities) {
+                    flags += "image-upload";
+                }
+
+                if (PluginCapabilities.VIDEO_UPLOAD in capabilities) {
+                    flags += "av-upload";
+                }
+
+                if (PluginCapabilities.AUDIO_UPLOAD in capabilities) {
+                    flags += "audio-upload";
+                }
+            }
+
+            if (allow_delete) {
+                flags += "create-item-with-OCM-destroy-item";
+            }
+
+        }
+
+        // Set the flags we found; otherwise remove whatever is in the
+        // template.
+        if (flags.length > 0) {
+            content = string.joinv (",", flags);
+        }
+
+        this.set_device_element ("X_DLNACAP", content);
+    }
+
+
+    /**
      * Change the type of a service.
      *
      * Usually used to modify the service version, e.g. old_type =
@@ -184,8 +237,8 @@ public class Rygel.DescriptionFile : Object {
                                          "root",
                                          "device",
                                          element);
-        assert (xml_element != null);
-
-        xml_element->set_content (new_value);
+        if (element != null) {
+            xml_element->set_content (new_value);
+        }
     }
 }
diff --git a/src/librygel-core/rygel-plugin.vala b/src/librygel-core/rygel-plugin.vala
index 9e89dc1..072b149 100644
--- a/src/librygel-core/rygel-plugin.vala
+++ b/src/librygel-core/rygel-plugin.vala
@@ -25,6 +25,33 @@ using Gee;
 using GUPnP;
 
 /**
+ * RygelPluginCapabilities is a set of flags that represent various
+ * capabilities of plugins.
+ */
+[Flags]
+public enum Rygel.PluginCapabilities {
+    NONE = 0,
+    /* Server caps */
+
+    /// Server plugin supports upload of images
+    IMAGE_UPLOAD,
+
+    /// Server plugin supports upload of video files
+    VIDEO_UPLOAD,
+
+    /// Server plugin supports upload of audio files
+    AUDIO_UPLOAD,
+
+    /// Server supports upload of all kind of items
+    UPLOAD = IMAGE_UPLOAD | VIDEO_UPLOAD | AUDIO_UPLOAD,
+
+    /// Server supports tracking changes
+    TRACK_CHANGES
+
+    /* Renderer caps */
+}
+
+/**
  * This represents a Rygel plugin.
  *
  * Plugin libraries should provide an object of this
@@ -64,6 +91,8 @@ public class Rygel.Plugin : GUPnP.ResourceFactory {
     private static const int ICON_SMALL_WIDTH = 48;
     private static const int ICON_SMALL_HEIGHT = 48;
 
+    public PluginCapabilities capabilities { get; protected set; }
+
     public string name { get; private set; }
     public string title { get; set; }
     public string description { get; private set; }
@@ -95,11 +124,13 @@ public class Rygel.Plugin : GUPnP.ResourceFactory {
     public Plugin (string  desc_path,
                    string  name,
                    string? title,
-                   string? description = null) {
+                   string? description = null,
+                   PluginCapabilities capabilities = PluginCapabilities.NONE) {
         this.desc_path = desc_path;
         this.name = name;
         this.title = title;
         this.description = description;
+        this.capabilities = capabilities;
 
         this.active = true;
 
diff --git a/src/librygel-core/rygel-root-device-factory.vala b/src/librygel-core/rygel-root-device-factory.vala
index a23bc0a..ed6afad 100644
--- a/src/librygel-core/rygel-root-device-factory.vala
+++ b/src/librygel-core/rygel-root-device-factory.vala
@@ -85,6 +85,7 @@ public class Rygel.RootDeviceFactory {
         this.prepare_desc_for_plugin (doc, plugin);
 
         var file = new DescriptionFile.from_xml_document (doc);
+        file.set_dlna_caps (plugin.capabilities);
         file.save (desc_path);
 
         return doc;
@@ -107,7 +108,6 @@ public class Rygel.RootDeviceFactory {
         this.set_friendly_name_and_udn (device_element,
                                         plugin.name,
                                         plugin.title);
-        this.set_dlnacap (device_element);
 
         if (plugin.description != null) {
             this.set_description (device_element, plugin.description);
@@ -167,30 +167,6 @@ public class Rygel.RootDeviceFactory {
         }
     }
 
-    private void set_dlnacap (Xml.Node *device_element) {
-        var element = XMLUtils.get_element (device_element,
-                                            "X_DLNACAP",
-                                            null);
-
-        var content = "";
-        var allow_upload = true;
-        var allow_delete = false;
-
-        try {
-            allow_upload = config.get_allow_upload ();
-            allow_delete = config.get_allow_deletion ();
-        } catch (Error error) { }
-
-        if (allow_upload) {
-            content += "av-upload,image-upload,audio-upload";
-        }
-
-        if (allow_delete) {
-            content += ",create-item-with-OCM-destroy-item";
-        }
-        element->set_content (content);
-    }
-
     private void set_description (Xml.Node *device_element,
                                   string    description) {
         Xml.Node *element = XMLUtils.get_element (device_element,
diff --git a/src/librygel-renderer/rygel-media-renderer-plugin.vala b/src/librygel-renderer/rygel-media-renderer-plugin.vala
index e2c4109..872963b 100644
--- a/src/librygel-renderer/rygel-media-renderer-plugin.vala
+++ b/src/librygel-renderer/rygel-media-renderer-plugin.vala
@@ -44,8 +44,10 @@ public class Rygel.MediaRendererPlugin : Rygel.Plugin {
      */
     public MediaRendererPlugin (string  name,
                                 string? title,
-                                string? description = null) {
-        base (MEDIA_RENDERER_DESC_PATH, name, title, description);
+                                string? description = null,
+                                PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
+        base (MEDIA_RENDERER_DESC_PATH, name, title, description, capabilities);
 
         var resource = new ResourceInfo (ConnectionManager.UPNP_ID,
                                          ConnectionManager.UPNP_TYPE,
diff --git a/src/librygel-renderer/rygel-media-renderer.vala b/src/librygel-renderer/rygel-media-renderer.vala
index d96888b..df9ce27 100644
--- a/src/librygel-renderer/rygel-media-renderer.vala
+++ b/src/librygel-renderer/rygel-media-renderer.vala
@@ -22,8 +22,9 @@
 internal class Plugin : Rygel.MediaRendererPlugin {
     private Rygel.MediaPlayer player;
 
-    public Plugin (Rygel.MediaPlayer root_container) {
-        base ("LibRygelRenderer", _("LibRygelRenderer"));
+    public Plugin (Rygel.MediaPlayer root_container,
+                   Rygel.PluginCapabilities capabilities) {
+        base ("LibRygelRenderer", _("LibRygelRenderer"), null, capabilities);
     }
 
     public override Rygel.MediaPlayer? get_player () {
@@ -44,9 +45,12 @@ public class Rygel.MediaRenderer : MediaDevice {
     /**
      * Create a RygelMediaRenderer to render content via a RygelMediaPlayer.
      */
-    public MediaRenderer (string title, MediaPlayer player) {
+    public MediaRenderer (string title,
+                          MediaPlayer player,
+                          PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
         base ();
-        this.plugin = new global::Plugin (player);
+        this.plugin = new global::Plugin (player, capabilities);
         this.plugin.title = title;
     }
 }
diff --git a/src/librygel-server/rygel-content-directory.vala b/src/librygel-server/rygel-content-directory.vala
index c6e1ffe..93c8aa8 100644
--- a/src/librygel-server/rygel-content-directory.vala
+++ b/src/librygel-server/rygel-content-directory.vala
@@ -52,6 +52,8 @@ internal class Rygel.ContentDirectory: Service {
     public const string UPNP_TYPE_V1 =
                     "urn:schemas-upnp-org:service:ContentDirectory:1";
     public const string DESCRIPTION_PATH = "xml/ContentDirectory.xml";
+    public const string DESCRIPTION_PATH_NO_TRACK =
+                    "xml/ContentDirectory-NoTrack.xml";
 
     protected string feature_list;
 
diff --git a/src/librygel-server/rygel-media-server-plugin.vala b/src/librygel-server/rygel-media-server-plugin.vala
index 56297f8..d187893 100644
--- a/src/librygel-server/rygel-media-server-plugin.vala
+++ b/src/librygel-server/rygel-media-server-plugin.vala
@@ -43,18 +43,26 @@ public abstract class Rygel.MediaServerPlugin : Rygel.Plugin {
      */
     public MediaServerPlugin (MediaContainer root_container,
                               string         name,
-                              string?        description = null) {
+                              string?        description = null,
+                              PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
         base (MEDIA_SERVER_DESC_PATH,
               name,
               root_container.title,
-              description);
+              description,
+              capabilities);
 
         this.root_container = root_container;
+        var path = ContentDirectory.DESCRIPTION_PATH_NO_TRACK;
 
         // MediaServer implementations must implement ContentDirectory service
+        if (PluginCapabilities.TRACK_CHANGES in this.capabilities) {
+            path = ContentDirectory.DESCRIPTION_PATH;
+        }
+
         var info = new ResourceInfo (ContentDirectory.UPNP_ID,
                                      ContentDirectory.UPNP_TYPE,
-                                     ContentDirectory.DESCRIPTION_PATH,
+                                     path,
                                      typeof (ContentDirectory));
         this.add_resource (info);
 
diff --git a/src/librygel-server/rygel-media-server.vala b/src/librygel-server/rygel-media-server.vala
index eee9018..4a1408d 100644
--- a/src/librygel-server/rygel-media-server.vala
+++ b/src/librygel-server/rygel-media-server.vala
@@ -20,8 +20,9 @@
  */
 
 internal class Plugin : Rygel.MediaServerPlugin {
-    public Plugin (Rygel.MediaContainer root_container) {
-        base (root_container, _("LibRygelServer"));
+    public Plugin (Rygel.MediaContainer root_container,
+                   Rygel.PluginCapabilities capabilities) {
+        base (root_container, _("LibRygelServer"), null, capabilities);
     }
 }
 
@@ -45,9 +46,12 @@ public class Rygel.MediaServer : MediaDevice {
      * the RygelMediaServer will respond appropriately to changes in the
      * RygelMediaContainer. 
      */
-    public MediaServer (string title, MediaContainer root_container) {
+    public MediaServer (string title,
+                        MediaContainer root_container,
+                        PluginCapabilities capabilities =
+                                        PluginCapabilities.NONE) {
         base ();
-        this.plugin = new global::Plugin (root_container);
+        this.plugin = new global::Plugin (root_container, capabilities);
         this.plugin.title = title;
     }
 }
diff --git a/src/plugins/media-export/rygel-media-export-plugin.vala b/src/plugins/media-export/rygel-media-export-plugin.vala
index fe5d359..42df8b3 100644
--- a/src/plugins/media-export/rygel-media-export-plugin.vala
+++ b/src/plugins/media-export/rygel-media-export-plugin.vala
@@ -105,6 +105,9 @@ public class Rygel.MediaExport.Plugin : Rygel.MediaServerPlugin {
     public const string NAME = "MediaExport";
 
     public Plugin () throws Error {
-        base (RootContainer.get_instance (), NAME);
+        base (RootContainer.get_instance (),
+              NAME,
+              null,
+              PluginCapabilities.UPLOAD);
     }
 }
diff --git a/src/plugins/tracker/rygel-tracker-plugin.vala b/src/plugins/tracker/rygel-tracker-plugin.vala
index 765a5d2..c5c88c9 100644
--- a/src/plugins/tracker/rygel-tracker-plugin.vala
+++ b/src/plugins/tracker/rygel-tracker-plugin.vala
@@ -34,7 +34,7 @@ public class Rygel.Tracker.Plugin : Rygel.MediaServerPlugin {
             root = new RootContainer (_("@REALNAME@'s media"));
         }
 
-        base (root, Plugin.NAME);
+        base (root, Plugin.NAME, null, PluginCapabilities.UPLOAD);
     }
 }
 



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