[rygel] server,data: Implement CreateReference UPnP call



commit 8d1a6fd17c76146da4db2e13e7d349addc9501e5
Author: Jens Georg <jensg openismus com>
Date:   Thu Feb 28 14:58:36 2013 +0100

    server,data: Implement CreateReference UPnP call
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694179

 data/xml/ContentDirectory.xml.in                  |   22 ++++
 src/librygel-server/filelist.am                   |    1 +
 src/librygel-server/rygel-content-directory.vala  |   10 ++
 src/librygel-server/rygel-reference-creator.vala  |  125 +++++++++++++++++++++
 src/librygel-server/rygel-writable-container.vala |   14 +++
 5 files changed, 172 insertions(+), 0 deletions(-)
---
diff --git a/data/xml/ContentDirectory.xml.in b/data/xml/ContentDirectory.xml.in
index 81b82c6..e7db30d 100644
--- a/data/xml/ContentDirectory.xml.in
+++ b/data/xml/ContentDirectory.xml.in
@@ -367,6 +367,28 @@
       </action>
 
       <action>
+         <name>CreateReference</name>
+         <argumentList>
+            <argument>
+               <name>ContainerID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>ObjectID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>NewID</name>
+               <direction>out</direction>
+               <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
+
+
+      <action>
          <name>ImportResource</name>
          <argumentList>
             <argument>
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am
index 71d05c6..d0dfa3f 100644
--- a/src/librygel-server/filelist.am
+++ b/src/librygel-server/filelist.am
@@ -52,6 +52,7 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
        rygel-http-transcode-handler.vala \
        rygel-import-resource.vala \
        rygel-object-creator.vala \
+       rygel-reference-creator.vala \
        rygel-item-destroyer.vala \
        rygel-item-updater.vala \
        rygel-object-removal-queue.vala \
diff --git a/src/librygel-server/rygel-content-directory.vala 
b/src/librygel-server/rygel-content-directory.vala
index ecef0f4..8ac31b9 100644
--- a/src/librygel-server/rygel-content-directory.vala
+++ b/src/librygel-server/rygel-content-directory.vala
@@ -132,6 +132,8 @@ internal class Rygel.ContentDirectory: Service {
         this.action_invoked["Browse"].connect (this.browse_cb);
         this.action_invoked["Search"].connect (this.search_cb);
         this.action_invoked["CreateObject"].connect (this.create_object_cb);
+        this.action_invoked["CreateReference"].connect
+                                        (this.create_reference_cb);
         this.action_invoked["DestroyObject"].connect (this.destroy_object_cb);
         this.action_invoked["UpdateObject"].connect (this.update_object_cb);
         this.action_invoked["ImportResource"].connect (this.import_resource_cb);
@@ -208,6 +210,14 @@ internal class Rygel.ContentDirectory: Service {
         creator.run.begin ();
     }
 
+    /* CreateReference action implementation */
+    private void create_reference_cb (Service       content_dir,
+                                      ServiceAction action) {
+        var creator = new ReferenceCreator (this, action);
+
+        creator.run.begin ();
+    }
+
     /* DestroyObject action implementation */
     private void destroy_object_cb (Service       content_dir,
                                     ServiceAction action) {
diff --git a/src/librygel-server/rygel-reference-creator.vala 
b/src/librygel-server/rygel-reference-creator.vala
new file mode 100644
index 0000000..65fd1e8
--- /dev/null
+++ b/src/librygel-server/rygel-reference-creator.vala
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * Author: Jens Georg <jensg openismus 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;
+
+internal class Rygel.ReferenceCreator : GLib.Object, Rygel.StateMachine {
+    private ContentDirectory content_directory;
+    private ServiceAction action;
+
+    // Props
+    public Cancellable cancellable { get; set; }
+    public string container_id;
+
+    // Local props
+    public string object_id;
+
+    public ReferenceCreator (ContentDirectory    content_dir,
+                             owned ServiceAction action) {
+        this.content_directory = content_dir;
+        this.cancellable = content_dir.cancellable;
+        this.action = (owned) action;
+    }
+
+    public void parse_arguments () throws Error {
+        this.action.get ("ContainerID",
+                            typeof (string), out this.container_id,
+                         "ObjectID",
+                             typeof (string), out this.object_id);
+        if (this.container_id == null) {
+            // FIXME: Add translation
+            throw new ContentDirectoryError.INVALID_ARGS
+                                        (("'ContainerID' agument missing."));
+        }
+
+        if (this.object_id == null) {
+            // FIXME: Add translation
+            throw new ContentDirectoryError.INVALID_ARGS
+                                        (("'ObjectID' argument missing."));
+        }
+    }
+
+    public async void run () {
+        try {
+            this.parse_arguments ();
+            var container = yield this.fetch_container ();
+            var root_container = this.content_directory.root_container;
+            var object = yield root_container.find_object
+                                        (this.object_id, this.cancellable);
+            if (object == null) {
+                throw new ContentDirectoryError.NO_SUCH_OBJECT
+                                        (_("No such object"));
+            }
+
+            var new_id = yield container.add_reference (object,
+                                                        this.cancellable);
+
+            this.action.set ("NewID", typeof (string), new_id);
+            this.action.return ();
+            this.completed ();
+        } catch (Error error) {
+            this.action.return_error (error.code, error.message);
+
+            warning (_("Failed to create object under '%s': %s"),
+                     this.container_id,
+                     error.message);
+
+            this.completed ();
+
+            return;
+        }
+    }
+
+    /**
+     * Get the container to create the item in.
+     *
+     * This will either try to fetch the container supplied by the caller or
+     * search for a container if the caller supplied the "DLNA.ORG_AnyContainer"
+     * id.
+     *
+     * @return an instance of WritableContainer matching the criteria
+     * @throws ContentDirectoryError for various problems
+     */
+    private async WritableContainer fetch_container () throws Error {
+        MediaObject media_object = null;
+
+        var root_container = this.content_directory.root_container;
+        media_object = yield root_container.find_object (this.container_id,
+                                                         this.cancellable);
+
+        if (media_object == null || !(media_object is MediaContainer)) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT
+                                        (_("No such object"));
+        } else if (!(OCMFlags.UPLOAD in media_object.ocm_flags) ||
+                   !(media_object is WritableContainer)) {
+            throw new ContentDirectoryError.RESTRICTED_PARENT
+                                        (_("Object creation in %s not allowed"),
+                                         media_object.id);
+        }
+
+        // FIXME: Check for @restricted=1 missing?
+
+        return media_object as WritableContainer;
+    }
+
+
+}
diff --git a/src/librygel-server/rygel-writable-container.vala 
b/src/librygel-server/rygel-writable-container.vala
index b6a384d..f6d0868 100644
--- a/src/librygel-server/rygel-writable-container.vala
+++ b/src/librygel-server/rygel-writable-container.vala
@@ -95,6 +95,20 @@ public interface Rygel.WritableContainer : MediaContainer {
     public async abstract void add_container (MediaContainer container,
                                               Cancellable?   cancellable)
                                               throws Error;
+
+    /**
+     * Add a reference to an object.
+     * @param object The source object to add a reference to.
+     * @param cancellable optional cancellable for this operation
+     * @return the id of the newly created reference
+     **/
+    public async virtual string add_reference (MediaObject    object,
+                                               Cancellable? cancellable)
+                                               throws Error {
+        throw new WriteableContainerError.NOT_IMPLEMENTED
+                                        ("Cannot create references here");
+    }
+
     /**
      * Remove an item directly under this container that has the ID @id.
      *


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