[rygel] core: Add get_children and get_object method



commit 1eb691e36712f2ef68fd8f8a9ff71ab30212649c
Author: Jens Georg <mail jensge org>
Date:   Fri Jun 5 00:25:31 2009 +0200

    core: Add get_children and get_object method

 src/rygel/Makefile.am                              |   10 +-
 .../rygel-database-backed-media-container.vala     |   71 +++++++++
 src/rygel/rygel-media-db-object-factory.vala       |   69 +++++++++
 src/rygel/rygel-media-db.vala                      |  158 +++++++++++++-------
 4 files changed, 252 insertions(+), 56 deletions(-)
---
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index a3b21fc..fcb1e6a 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -64,6 +64,8 @@ BUILT_SOURCES = rygel-1.0.vapi \
 		rygel-media-item.c \
 		rygel-metadata-extractor.c \
 		rygel-media-db.c \
+		rygel-database-backed-media-container.c \
+		rygel-media-db-object-factory.c \
 		rygel-mp2ts-transcoder.c \
 		rygel-mp3-transcoder.c \
 		rygel-l16-transcoder.c \
@@ -113,7 +115,9 @@ rygel_SOURCES = $(VAPI_SOURCE_FILES) \
 		rygel-mp2ts-transcoder-bin.c \
 		rygel-mp3-transcoder-bin.c \
 		rygel-l16-transcoder-bin.c \
-		rygel-gst-utils.c
+		rygel-gst-utils.c \
+		rygel-database-backed-media-container.c \
+		rygel-media-db-object-factory.c
 
 rygel.stamp: $(filter %.vala,$(rygel_SOURCES))
 	$(VALAC) -C --vapidir=$(srcdir) --thread \
@@ -170,7 +174,9 @@ VAPI_SOURCE_FILES = rygel-configuration.vala \
 		    rygel-mp3-transcoder-bin.vala \
 		    rygel-l16-transcoder-bin.vala \
 		    rygel-gst-utils.vala \
-		    rygel-media-db.vala
+		    rygel-media-db.vala \
+		    rygel-database-backed-media-container.vala \
+		    rygel-media-db-object-factory.vala
 
 rygel-1.0.vapi: $(VAPI_SOURCE_FILES)
 	$(VALAC) -H rygel.h -C --library=rygel-1.0 --vapidir=$(srcdir) \
diff --git a/src/rygel/rygel-database-backed-media-container.vala b/src/rygel/rygel-database-backed-media-container.vala
new file mode 100644
index 0000000..dd32a04
--- /dev/null
+++ b/src/rygel/rygel-database-backed-media-container.vala
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using Rygel;
+
+public class Rygel.DatabaseBackedMediaContainer : Rygel.MediaContainer {
+    private MediaDB media_db;
+
+    public DatabaseBackedMediaContainer (Rygel.MediaDB media_db,
+                                         string id,
+                                         string title) {
+        base (id, null, title, 0);
+
+        this.media_db = media_db;
+    }
+
+    public override void get_children (uint offset,
+                                       uint max_count,
+                                       Cancellable? cancellable,
+                                       AsyncReadyCallback callback) {
+        var res = new Rygel.SimpleAsyncResult<Gee.ArrayList<MediaObject>>
+                                                            (this, callback);
+        res.data = this.media_db.get_children (this.id,
+                                               offset,
+                                               max_count);
+        res.complete_in_idle ();
+    }
+
+    public override Gee.List<MediaObject>? get_children_finish (
+                                                           AsyncResult res)
+                                                           throws GLib.Error {
+        return ((Rygel.SimpleAsyncResult<Gee.ArrayList<MediaObject>>)res).data;
+    }
+
+
+    public override void find_object (string id,
+                                      Cancellable? cancellable,
+                                      AsyncReadyCallback callback) {
+        var res = new Rygel.SimpleAsyncResult<MediaObject> (this, callback);
+
+        res.data = media_db.get_object (id);
+        res.complete_in_idle ();
+    }
+
+    public override MediaObject? find_object_finish (AsyncResult res) {
+        return ((Rygel.SimpleAsyncResult<MediaObject>)res).data;
+    }
+}
+
+
diff --git a/src/rygel/rygel-media-db-object-factory.vala b/src/rygel/rygel-media-db-object-factory.vala
new file mode 100644
index 0000000..b655d89
--- /dev/null
+++ b/src/rygel/rygel-media-db-object-factory.vala
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using Rygel;
+
+/**
+ * Class used by MediaDB to create containers and items on demand
+ *
+ * If a specific kind of Item or Container is needed instead of
+ * the default ones, inherit from this class and override the
+ * corresponding methods.
+ *
+ * The class does not hold a reference to the MediaDB as the
+ * MediaDB is holding a reference to the factory; this is done to
+ * prevent circular references
+ */
+public class Rygel.MediaDBObjectFactory : Object {
+    /**
+     * Return a new instance of DatabaseBackedMediaContainer
+     *
+     * @param media_db instance of MediaDB
+     * @param title title of the container
+     * @param child_count number of children in the container
+     */
+    public virtual MediaContainer get_container (Rygel.MediaDB media_db,
+                                                 string id,
+                                                 string title,
+                                                 uint child_count) {
+        return new DatabaseBackedMediaContainer (media_db,
+                                                 id,
+                                                 title);
+    }
+
+    /**
+     * Return a new instance of MediaItem
+     *
+     * @param media_db instance of MediaDB
+     * @param id id of the item
+     * @param title title of the item
+     * @param upnp_class upnp_class of the item
+     */
+    public virtual MediaItem get_item (Rygel.MediaDB media_db,
+                                       string id,
+                                       string title,
+                                       string upnp_class) {
+        return new MediaItem (id, null, title, upnp_class);
+    }
+}
diff --git a/src/rygel/rygel-media-db.vala b/src/rygel/rygel-media-db.vala
index 1cc5083..b630e47 100644
--- a/src/rygel/rygel-media-db.vala
+++ b/src/rygel/rygel-media-db.vala
@@ -37,6 +37,7 @@ public enum Rygel.MediaDBObjectType {
 
 public class Rygel.MediaDB : Object {
     private Database db;
+    private MediaDBObjectFactory factory;
     private const string schema_version = "3";
     private const string db_schema_v1 =
     "BEGIN;" +
@@ -88,14 +89,23 @@ public class Rygel.MediaDB : Object {
     private const string URI_INSERT_STRING =
     "INSERT INTO Uri (object_fk, uri) VALUES (?,?)";
 
-    private const string ITEM_GET_STRING =
-    "SELECT size, mime_type, width, height, class, Object.title, author, album, " +
-            "date, bitrate, sample_freq, bits_per_sample, channels, track, " +
-            "color_depth, duration " +
-    "FROM Meta_Data JOIN Object " +
+    private const string OBJECT_GET_STRING =
+    "SELECT Object.type_fk, Object.title, size, mime_type, width, height, " +
+            "class, author, album, date, bitrate, sample_freq, " +
+            "bits_per_sample, channels, track, color_depth, duration " +
+    "FROM Meta_Data LEFT OUTER JOIN Object " +
         "ON Object.metadata_fk = Meta_Data.id WHERE Object.upnp_id = ?";
 
-    public MediaDB (string name) {
+    private const string CHILDREN_GET_STRING =
+    "SELECT Object.type_fk, Object.title, size, mime_type, width, height, " +
+            "class, author, album, date, bitrate, sample_freq, " +
+            "bits_per_sample, channels, track, color_depth, duration " +
+    "FROM Meta_Data LEFT OUTER JOIN Object " +
+        "ON Object.metadata_fk = Meta_Data.id " +
+    "WHERE Object.parent = ? " +
+    "LIMIT ?,?";
+
+    private void open_db (string name) {
         var rc = Database.open (name, out this.db);
         if (rc != Sqlite.OK) {
             warning ("Failed to open database: %d, %s",
@@ -154,6 +164,16 @@ public class Rygel.MediaDB : Object {
         }
     }
 
+    public MediaDB (string name) {
+        open_db (name);
+        this.factory = new MediaDBObjectFactory ();
+    }
+
+    public MediaDB.with_factory (string name, MediaDBObjectFactory factory) {
+        open_db (name);
+        this.factory = factory;
+    }
+
     public signal void item_added (string item_id);
 
     public void save_object (MediaObject obj) throws Error {
@@ -169,7 +189,7 @@ public class Rygel.MediaDB : Object {
     public void save_container (MediaContainer container) throws Error {
         var rc = db.exec ("BEGIN");
         try {
-            save_object (container, -1);
+            create_object (container, -1);
             rc = db.exec ("COMMIT");
         } catch (Error error) {
             rc = db.exec ("ROLLBACK");
@@ -180,7 +200,7 @@ public class Rygel.MediaDB : Object {
         var rc = db.exec ("BEGIN;");
         try {
             var id = save_metadata (item);
-            save_object (item, id);
+            create_object (item, id);
             save_uris (item);
             rc = db.exec ("COMMIT;");
             if (rc == Sqlite.OK) {
@@ -228,7 +248,7 @@ public class Rygel.MediaDB : Object {
         }
     }
 
-    private void save_object (MediaObject item, int64 metadata_id) throws Error {
+    private void create_object (MediaObject item, int64 metadata_id) throws Error {
         Statement statement;
 
         var rc = db.prepare_v2 (OBJECT_INSERT_STRING,
@@ -253,7 +273,7 @@ public class Rygel.MediaDB : Object {
                 statement.bind_int64 (4, metadata_id);
             }
 
-            if (item.parent == null || item.parent.id == "0") {
+            if (item.parent == null) {
                 statement.bind_null (5);
             } else {
                 statement.bind_text (5, item.parent.id);
@@ -312,65 +332,95 @@ public class Rygel.MediaDB : Object {
         }
     }
 
-    public MediaItem? get_item (string item_id) {
-        var item = new MediaItem ("", null, "", "");
-        try {
-            fill_object (item_id, ref item);
-        } catch (Error error) {
-            item = null;
+    private MediaObject? get_object_from_statement (string object_id, Statement statement) {
+        MediaObject obj = null;
+        switch (statement.column_int (0)) {
+            case 0:
+                // this is a container
+                obj = factory.get_container (this,
+                        object_id,
+                        statement.column_text (1),
+                        0);
+                break;
+            case 1:
+                // this is an item
+                obj = factory.get_item (this,
+                        object_id,
+                        statement.column_text (1),
+                        statement.column_text (6));
+                fill_item (statement, (MediaItem)obj);
+                break;
+            default:
+                // should not happen
+                break;
         }
 
-        return item;
-    }
-
-    private void fill_container (string object_id, ref MediaContainer container) {
-
+        return null;
     }
 
-    private void fill_item (string object_id, ref MediaItem item) {
+    public MediaObject? get_object (string object_id) {
+        MediaObject obj = null;
         Statement statement;
-        var rc = db.prepare_v2 (ITEM_GET_STRING,
+
+        // decide what kind of object this is
+        var rc = db.prepare_v2 (OBJECT_GET_STRING,
                                 -1,
                                 out statement,
                                 null);
         if (rc == Sqlite.OK) {
             statement.bind_text (1, object_id);
             while ((rc = statement.step ()) == Sqlite.ROW) {
-                item.id = object_id;
-                item.title = statement.column_text (5);
-                item.upnp_class = statement.column_text (4);
-
-                item.author = statement.column_text (6);
-                item.album = statement.column_text (7);
-                item.date = statement.column_text (8);
-                item.mime_type = statement.column_text (1);
-                item.duration = (long)statement.column_text (15);
-
-                item.size = (long)statement.column_int64 (0);
-                item.bitrate = statement.column_int (9);
-
-                item.sample_freq = statement.column_int (10);
-                item.bits_per_sample = statement.column_int (11);
-                item.n_audio_channels = statement.column_int (12);
-                item.track_number = statement.column_int (13);
-
-                item.width = statement.column_int (2);
-                item.height = statement.column_int (3);
-                item.color_depth = statement.column_int (14);
+                obj = get_object_from_statement (object_id, statement);
                 break;
             }
+        } else {
         }
+
+        return obj;
     }
 
-    public void fill_object (string object_id, ref MediaObject obj) throws Error {
-        if (obj is MediaItem) {
-            MediaItem item = (MediaItem) obj;
-            fill_item (object_id, ref item);
-        } else if (obj is MediaContainer) {
-            MediaContainer container = (MediaContainer) obj;
-            fill_container (object_id, ref container);
-        } else {
-            throw new MediaDBError.GENERAL_ERROR ("Invalid object type");
-        }
+    private void fill_item (Statement statement, MediaItem item) {
+        item.author = statement.column_text (7);
+        item.album = statement.column_text (8);
+        item.date = statement.column_text (9);
+        item.mime_type = statement.column_text (3);
+        item.duration = (long)statement.column_text (16);
+
+        item.size = (long)statement.column_int64 (2);
+        item.bitrate = statement.column_int (10);
+
+        item.sample_freq = statement.column_int(11);
+        item.bits_per_sample = statement.column_int (12);
+        item.n_audio_channels = statement.column_int (13);
+        item.track_number = statement.column_int (14);
+
+        item.width = statement.column_int (4);
+        item.height = statement.column_int (5);
+        item.color_depth = statement.column_int (15);
     }
 
+    public Gee.ArrayList<MediaObject>? get_children (string object_id,
+                                                      uint offset,
+                                                      uint max_count) {
+        Statement statement;
+        Gee.ArrayList<MediaObject> children = null;
+        var rc = db.prepare_v2 (CHILDREN_GET_STRING,
+                                -1,
+                                out statement,
+                                null);
+        if (rc == Sqlite.OK) {
+            statement.bind_text (1, object_id);
+            statement.bind_int64 (2, (int64)offset);
+            statement.bind_int64 (3, (int64)max_count);
+            while ((rc = statement.step ()) == Sqlite.ROW) {
+                if (children == null) {
+                    children = new Gee.ArrayList<MediaObject> ();
+                }
+
+                children.add (get_object_from_statement (object_id, statement));
+            }
+        }
+
+        return children;
+    }
+}



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