summaryrefslogtreecommitdiff
path: root/src/librygel-server/rygel-media-object.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/librygel-server/rygel-media-object.vala')
-rw-r--r--src/librygel-server/rygel-media-object.vala203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/librygel-server/rygel-media-object.vala b/src/librygel-server/rygel-media-object.vala
new file mode 100644
index 00000000..b5ffcfea
--- /dev/null
+++ b/src/librygel-server/rygel-media-object.vala
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2008 Zeeshan Ali <zeenix@gmail.com>.
+ *
+ * Author: Zeeshan Ali <zeenix@gmail.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;
+using Gee;
+
+/**
+ * Represents a media object (container and item).
+ */
+public abstract class Rygel.MediaObject : GLib.Object {
+ private static Regex real_name_regex;
+ private static Regex user_name_regex;
+ private static Regex host_name_regex;
+
+ public string id;
+ public string ref_id;
+ public string upnp_class;
+ public uint64 modified;
+ public Gee.ArrayList<string> uris;
+
+ // You can keep both a unowned and owned ref to parent of this MediaObject.
+ // In most cases, one will only need to keep an unowned ref to avoid cyclic
+ // references since usually parent container will keep refs to child items.
+ // However in some cases, one only wants the parent to exist as long as the
+ // child exists and it is in those cases, you will want to use 'parent_ref'.
+ //
+ // You must set 'parent' if you set 'parent_ref' but the opposite is not
+ // mandatory.
+ public unowned MediaContainer parent;
+ private MediaContainer _parent_ref;
+ public MediaContainer parent_ref {
+ get {
+ return this._parent_ref;
+ }
+
+ set {
+ this.parent = value;
+ this._parent_ref = value;
+ }
+ }
+
+ private string _title;
+ public string title {
+ get {
+ return _title;
+ }
+
+ set {
+ try {
+ this._title = real_name_regex.replace_literal
+ (value,
+ -1,
+ 0,
+ Environment.get_real_name ());
+ this._title = user_name_regex.replace_literal
+ (this._title,
+ -1,
+ 0,
+ Environment.get_user_name ());
+ this._title = host_name_regex.replace_literal
+ (this._title,
+ -1,
+ 0,
+ Environment.get_host_name ());
+ } catch (GLib.RegexError err) {
+ assert_not_reached ();
+ }
+ }
+ }
+
+ internal abstract OCMFlags ocm_flags { get; }
+
+ internal bool restricted {
+ get {
+ return this.ocm_flags == OCMFlags.NONE;
+ }
+ }
+
+ static construct {
+ try {
+ real_name_regex = new Regex (Regex.escape_string ("@REALNAME@"));
+ user_name_regex = new Regex (Regex.escape_string ("@USERNAME@"));
+ host_name_regex = new Regex (Regex.escape_string ("@HOSTNAME@"));
+ } catch (GLib.RegexError err) {
+ assert_not_reached ();
+ }
+ }
+
+ construct {
+ uris = new ArrayList<string> ();
+ }
+
+ /**
+ * Fetches a File object for any writable URI available for this object.
+ *
+ * @param cancellable A GLib.Cancellable
+ */
+ public async File? get_writable (Cancellable? cancellable) throws Error {
+ foreach (var uri in this.uris) {
+ var file = File.new_for_uri (uri);
+
+ if (yield this.check_writable (file, cancellable)) {
+ return file;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Fetches File objects for all writable URIs available for this object.
+ *
+ * @param cancellable A GLib.Cancellable
+ */
+ public async ArrayList<File> get_writables (Cancellable? cancellable)
+ throws Error {
+ var writables = new ArrayList<File> ();
+
+ foreach (var uri in this.uris) {
+ var file = File.new_for_uri (uri);
+
+ if (yield this.check_writable (file, cancellable)) {
+ writables.add (file);
+ }
+ }
+
+ return writables;
+ }
+
+ internal abstract DIDLLiteObject serialize (DIDLLiteWriter writer,
+ HTTPServer http_server)
+ throws Error;
+
+ internal virtual int compare_by_property (MediaObject media_object,
+ string property) {
+ switch (property) {
+ case "@id":
+ return this.compare_string_props (this.id, media_object.id);
+ case "@parentID":
+ return this.compare_string_props (this.parent.id,
+ media_object.parent.id);
+ case "dc:title":
+ return this.compare_string_props (this.title, media_object.title);
+ case "upnp:class":
+ return this.compare_string_props (this.upnp_class,
+ media_object.upnp_class);
+ default:
+ return 0;
+ }
+ }
+
+ protected int compare_string_props (string prop1, string prop2) {
+ if (prop1 == null) {
+ return -1;
+ } else if (prop2 == null) {
+ return 1;
+ } else {
+ return prop1.collate (prop2);
+ }
+ }
+
+ protected int compare_int_props (int prop1, int prop2) {
+ return (prop1 - prop2).clamp (-1, 1);
+ }
+
+ private async bool check_writable (File file, Cancellable? cancellable)
+ throws Error {
+ if (!file.is_native ()) {
+ return false;
+ }
+
+ try {
+ var info = yield file.query_info_async (
+ FileAttribute.ACCESS_CAN_WRITE,
+ FileQueryInfoFlags.NONE,
+ Priority.DEFAULT,
+ cancellable);
+
+ return info.get_attribute_boolean (FileAttribute.ACCESS_CAN_WRITE);
+ } catch (IOError.NOT_FOUND error) {
+ return true;
+ }
+ }
+}