[rygel] core: Implement 'CreateObject' action of CDS
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel] core: Implement 'CreateObject' action of CDS
- Date: Wed, 17 Feb 2010 13:40:24 +0000 (UTC)
commit 054e14f466b8663de9b20504c17c61a53bf85a8b
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Tue Jan 26 17:39:56 2010 +0200
core: Implement 'CreateObject' action of CDS
Currently we can only deal with 'no URI provided' case, i-e upload but OTOH
actual uploading isn't implemented yet. :)
data/xml/ContentDirectory.xml | 26 +++---
src/rygel/Makefile.am | 1 +
src/rygel/rygel-content-directory.vala | 10 +++
src/rygel/rygel-item-creator.vala | 138 ++++++++++++++++++++++++++++++++
src/rygel/rygel-media-container.vala | 31 +++++++
5 files changed, 193 insertions(+), 13 deletions(-)
---
diff --git a/data/xml/ContentDirectory.xml b/data/xml/ContentDirectory.xml
index c687d0d..a129d78 100644
--- a/data/xml/ContentDirectory.xml
+++ b/data/xml/ContentDirectory.xml
@@ -328,19 +328,6 @@ feature provided by your editor.
</argumentList>
</action>
-<!-- Optional actions that are not implemented yet
- <action>
- <Optional/>
- <name>GetSortExtensionCapabilities</name>
- <argumentList>
- <argument>
- <name>SortExtensionCaps</name>
- <direction>out</direction>
- <relatedStateVariable>SortExtensionCapabilities</relatedStateVariable>
- </argument>
- </argumentList>
- </action>
-
<action>
<Optional/>
<name>CreateObject</name>
@@ -368,6 +355,19 @@ feature provided by your editor.
</argumentList>
</action>
+<!-- Optional actions that are not implemented yet
+ <action>
+ <Optional/>
+ <name>GetSortExtensionCapabilities</name>
+ <argumentList>
+ <argument>
+ <name>SortExtensionCaps</name>
+ <direction>out</direction>
+ <relatedStateVariable>SortExtensionCapabilities</relatedStateVariable>
+ </argument>
+ </argumentList>
+ </action>
+
<action>
<Optional/>
<name>DestroyObject</name>
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index e83b227..2f72214 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -75,6 +75,7 @@ VAPI_SOURCE_FILES = rygel-configuration.vala \
rygel-thumbnailer.vala \
rygel-browse.vala \
rygel-search.vala \
+ rygel-item-creator.vala \
rygel-search-expression.vala \
rygel-relational-expression.vala \
rygel-logical-expression.vala \
diff --git a/src/rygel/rygel-content-directory.vala b/src/rygel/rygel-content-directory.vala
index 19a8da3..8615d35 100644
--- a/src/rygel/rygel-content-directory.vala
+++ b/src/rygel/rygel-content-directory.vala
@@ -30,6 +30,7 @@ using Gee;
*/
public errordomain Rygel.ContentDirectoryError {
NO_SUCH_OBJECT = 701,
+ RESTRICTED_PARENT = 713,
CANT_PROCESS = 720,
INVALID_ARGS = 402
}
@@ -97,6 +98,7 @@ public class Rygel.ContentDirectory: Service {
this.action_invoked["Browse"] += this.browse_cb;
this.action_invoked["Search"] += this.search_cb;
+ this.action_invoked["CreateObject"] += this.create_object_cb;
/* Connect SystemUpdateID related signals */
this.action_invoked["GetSystemUpdateID"] +=
@@ -145,6 +147,14 @@ public class Rygel.ContentDirectory: Service {
search.run.begin ();
}
+ /* CreateObject action implementation */
+ private virtual void create_object_cb (ContentDirectory content_dir,
+ owned ServiceAction action) {
+ var creator = new ItemCreator (this, action);
+
+ creator.run.begin ();
+ }
+
/* GetSystemUpdateID action implementation */
private void get_system_update_id_cb (ContentDirectory content_dir,
owned ServiceAction action) {
diff --git a/src/rygel/rygel-item-creator.vala b/src/rygel/rygel-item-creator.vala
new file mode 100644
index 0000000..a9e00ba
--- /dev/null
+++ b/src/rygel/rygel-item-creator.vala
@@ -0,0 +1,138 @@
+/*
+ * 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 GUPnP;
+
+/**
+ * CreateObject action implementation.
+ */
+internal class Rygel.ItemCreator: GLib.Object, Rygel.StateMachine {
+ // In arguments
+ public string container_id;
+ public string elements;
+
+ public DIDLLiteItem didl_item;
+ public MediaItem item;
+
+ private ContentDirectory content_dir;
+ private ServiceAction action;
+ private Rygel.DIDLLiteWriter didl_writer;
+ private DIDLLiteParser didl_parser;
+
+ public Cancellable cancellable { get; set; }
+
+ public ItemCreator (ContentDirectory content_dir,
+ owned ServiceAction action) {
+ this.content_dir = content_dir;
+ this.cancellable = content_dir.cancellable;
+ this.action = (owned) action;
+ this.didl_writer = new Rygel.DIDLLiteWriter (content_dir.http_server);
+ this.didl_parser = new DIDLLiteParser ();
+ }
+
+ public async void run () {
+ try {
+ this.parse_args ();
+
+ var container = yield this.fetch_container ();
+
+ this.didl_parser.item_available.connect ((didl_item) => {
+ this.didl_item = didl_item;
+ });
+ this.didl_parser.parse_didl (this.elements);
+
+ this.item = new MediaItem (didl_item.id,
+ container,
+ didl_item.title,
+ didl_item.upnp_class);
+ this.item.mime_type = this.get_generic_mime_type ();
+ this.item.place_holder = true;
+
+ yield container.add_item (this.item, this.cancellable);
+ this.didl_writer.serialize (this.item);
+
+ // Conclude the successful action
+ this.conclude ();
+ } catch (Error err) {
+ this.handle_error (err);
+ }
+ }
+
+ private async void parse_args () throws Error {
+ /* Start by parsing the 'in' arguments */
+ this.action.get ("ContainerID", typeof (string), out this.container_id,
+ "Elements", typeof (string), out this.elements);
+
+ if (this.container_id == null || this.elements == null) {
+ // Sorry we can't do anything without ContainerID
+ throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+ }
+ }
+
+ private async MediaContainer fetch_container () throws Error {
+ var media_object = yield this.content_dir.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");
+ }
+
+ return media_object as MediaContainer;
+ }
+
+ private void conclude () {
+ /* Retrieve generated string */
+ string didl = this.didl_writer.get_string ();
+
+ /* Set action return arguments */
+ this.action.set ("Result", typeof (string), didl,
+ "ObjectID", typeof (string), this.item.id);
+
+ this.action.return ();
+ this.completed ();
+ }
+
+ private void handle_error (Error error) {
+ if (error is ContentDirectoryError) {
+ this.action.return_error (error.code, error.message);
+ } else {
+ this.action.return_error (701, error.message);
+ }
+
+ warning ("Failed to create '%s': %s", this.item.id, error.message);
+
+ this.completed ();
+ }
+
+ private string get_generic_mime_type () {
+ switch (this.item.upnp_class) {
+ case MediaItem.IMAGE_CLASS:
+ return "image";
+ case MediaItem.VIDEO_CLASS:
+ return "video";
+ case MediaItem.AUDIO_CLASS:
+ default:
+ return "audio";
+ }
+ }
+}
+
diff --git a/src/rygel/rygel-media-container.vala b/src/rygel/rygel-media-container.vala
index 8ce6519..0dd0677 100644
--- a/src/rygel/rygel-media-container.vala
+++ b/src/rygel/rygel-media-container.vala
@@ -159,6 +159,37 @@ public abstract class Rygel.MediaContainer : MediaObject {
}
/**
+ * Add a new item directly under this container.
+ *
+ * @param didl_item The item to add to this container.
+ *
+ * return nothing.
+ *
+ * This implementation is very basic: It only creates the file under the
+ * first writable URI it can find for this container & sets the ID of the
+ * item to that of the URI of the newly created item. If your subclass
+ * doesn't ID the items by their original URIs, you definitely want to
+ * override this method.
+ */
+ public async virtual void add_item (MediaItem item,
+ Cancellable? cancellable)
+ throws Error {
+ var dir = yield this.get_writable (cancellable);
+ if (dir == null) {
+ throw new ContentDirectoryError.RESTRICTED_PARENT (
+ "Object creation in %s no allowed",
+ this.id);
+ }
+
+ var file = dir.get_child_for_display_name (item.title);
+ yield file.create_async (FileCreateFlags.NONE,
+ Priority.DEFAULT,
+ cancellable);
+ var uri = file.get_uri ();
+ item.id = uri;
+ }
+
+ /**
* Method to be be called each time this container is updated (metadata
* changes for this container, items under it gets removed/added or their
* metadata changes etc).
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]