[rygel/wip/dvd: 239/240] media-export: Query DVD structure information



commit 3fad19162771ddf8afebff2513674afe0a94e2f5
Author: Jens Georg <jensg openismus com>
Date:   Sun Jul 14 14:55:12 2013 +0200

    media-export: Query DVD structure information
    
    Use lsdvd binary and its XML output for this to avoid effective GPL
    relicensing by using libdvdread explicitly.
    
    The output is cached so we only have to do this once ideally.

 configure.ac                                       |    1 +
 src/plugins/media-export/Makefile.am               |    1 +
 .../rygel-media-export-dvd-parser.vala             |  126 ++++++++++++++++++++
 .../media-export/rygel-media-export-harvester.vala |    3 +-
 .../rygel-media-export-metadata-extractor.vala     |   48 +++++---
 5 files changed, 160 insertions(+), 19 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a7955aa..a8142d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -190,6 +190,7 @@ AS_IF([test "x$with_media_engine" = "xgstreamer"],
                                libsoup-2.4 >= $LIBSOUP_REQUIRED
                                sqlite3 >= $LIBSQLITE3_REQUIRED
                                libmediaart-2.0 >= $MEDIAART_REQUIRED])
+                               libxml-2.0 >= $LIBXML_REQUIRED
             RYGEL_PLUGIN_MEDIA_EXPORT_DEPS_VALAFLAGS="$RYGEL_COMMON_MODULES_VALAFLAGS --pkg gupnp-dlna-2.0 
--pkg gupnp-dlna-gst-2.0 --pkg gstreamer-tag-1.0 --pkg gstreamer-app-1.0 --pkg gstreamer-pbutils-1.0 --pkg 
sqlite3 --pkg libmediaart-2.0"
             AC_SUBST([RYGEL_PLUGIN_MEDIA_EXPORT_DEPS_VALAFLAGS])
           ])
diff --git a/src/plugins/media-export/Makefile.am b/src/plugins/media-export/Makefile.am
index 4916bcc..8d93997 100644
--- a/src/plugins/media-export/Makefile.am
+++ b/src/plugins/media-export/Makefile.am
@@ -7,6 +7,7 @@ librygel_media_export_la_SOURCES = \
        rygel-media-export-plugin.vala \
        rygel-media-export-database.vala \
        rygel-media-export-database-cursor.vala \
+       rygel-media-export-dvd-parser.vala \
        rygel-media-export-sqlite-wrapper.vala \
        rygel-media-export-db-container.vala \
        rygel-media-export-sql-factory.vala \
diff --git a/src/plugins/media-export/rygel-media-export-dvd-parser.vala 
b/src/plugins/media-export/rygel-media-export-dvd-parser.vala
new file mode 100644
index 0000000..b4a4fef
--- /dev/null
+++ b/src/plugins/media-export/rygel-media-export-dvd-parser.vala
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge 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.
+ */
+
+internal class Rygel.MediaExport.DVDParser : GLib.Object {
+    /// URI to the image / toplevel directory
+    public File file { private get; construct; }
+
+    private File cache_file;
+
+    public DVDParser (File file) {
+        Object (file : file);
+    }
+
+    public override void constructed () {
+        unowned string user_cache = Environment.get_user_cache_dir ();
+        var cache_folder = Path.build_filename (user_cache,
+                                                "rygel",
+                                                "dvd-content");
+        DirUtils.create_with_parents (cache_folder, 0700);
+        var cache_path = Path.build_filename (cache_folder,
+                                              MediaCache.get_id (this.file));
+
+        this.cache_file = File.new_for_path (cache_path);
+    }
+
+    public async void run () {
+        var doc = yield this.get_information ();
+        if (doc != null) {
+            doc->children;
+        }
+    }
+
+    public async Xml.Doc* get_information () {
+        if (this.cache_file.query_exists ()) {
+            return Xml.Parser.read_file (this.cache_file.get_path (),
+                                         null,
+                                         Xml.ParserOption.NOERROR |
+                                         Xml.ParserOption.NOWARNING);
+        }
+
+        Pid pid;
+        int stdout_fd;
+
+        try {
+            Process.spawn_async_with_pipes (null,
+                                            { "/usr/bin/lsdvd",
+                                              "-Ox",
+                                              "-x",
+                                              "-q",
+                                              this.file.get_path (),
+                                              null },
+                                            null,
+                                            SpawnFlags.DO_NOT_REAP_CHILD |
+                                            SpawnFlags.STDERR_TO_DEV_NULL,
+                                            null,
+                                            out pid,
+                                            null,
+                                            out stdout_fd);
+            var data = new StringBuilder ();
+            var io_channel = new IOChannel.unix_new (stdout_fd);
+            var io_watch = io_channel.add_watch (IOCondition.IN |
+                                                 IOCondition.PRI,
+                                                 () => {
+                string line;
+
+                try {
+                    io_channel.read_to_end (out line, null);
+                    data.append (line);
+                } catch (Error error) { }
+
+                return true;
+            });
+
+            uint child_watch = 0;
+            child_watch = ChildWatch.add (pid, () => {
+                Source.remove (child_watch);
+                Source.remove (io_watch);
+                Process.close_pid (pid);
+
+                get_information.callback ();
+            });
+
+            yield;
+
+            try {
+                this.cache_file.replace_contents (data.str.data,
+                                                  null,
+                                                  false,
+                                                  FileCreateFlags.NONE,
+                                                  null);
+            } catch (Error rc_error) {
+                debug ("Failed to cache lsdvd output: %s", rc_error.message);
+            }
+
+            return Xml.Parser.read_memory (data.str,
+                                           (int) data.len,
+                                           null,
+                                           null,
+                                           Xml.ParserOption.NOERROR |
+                                           Xml.ParserOption.NOWARNING);
+        } catch (SpawnError error) {
+            debug ("Failed to run lsdvd: %s", error.message);
+        }
+
+        return null;
+    }
+}
diff --git a/src/plugins/media-export/rygel-media-export-harvester.vala 
b/src/plugins/media-export/rygel-media-export-harvester.vala
index 1c9038b..18420f3 100644
--- a/src/plugins/media-export/rygel-media-export-harvester.vala
+++ b/src/plugins/media-export/rygel-media-export-harvester.vala
@@ -73,7 +73,8 @@ internal class Rygel.MediaExport.Harvester : GLib.Object {
                info.get_content_type () == "application/ogg" ||
                info.get_content_type () == "application/xml" ||
                info.get_content_type () == "text/xml" ||
-               info.get_content_type () == "text/plain";
+               info.get_content_type () == "text/plain" ||
+               info.get_content_type () == "application/x-cd-image";
     }
 
     /**
diff --git a/src/plugins/media-export/rygel-media-export-metadata-extractor.vala 
b/src/plugins/media-export/rygel-media-export-metadata-extractor.vala
index 4d00778..a173ae1 100644
--- a/src/plugins/media-export/rygel-media-export-metadata-extractor.vala
+++ b/src/plugins/media-export/rygel-media-export-metadata-extractor.vala
@@ -59,6 +59,8 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object {
 
     private bool extract_metadata;
 
+    private DVDParser dvd_parser;
+
     public MetadataExtractor () {
         this.file_hash = new HashMap<string, File> ();
 
@@ -68,26 +70,36 @@ public class Rygel.MediaExport.MetadataExtractor: GLib.Object {
     }
 
     public void extract (File file, string content_type) {
-        if (this.extract_metadata && !content_type.has_prefix ("text/")) {
-            string uri = file.get_uri ();
-            try {
-                var gst_timeout = (ClockTime) (this.timeout * Gst.SECOND);
+        if (!this.extract_metadata || content_type.has_prefix ("text/")) {
+            this.extract_basic_information (file, null, null);
 
-                this.discoverer = new Discoverer (gst_timeout);
-            } catch (Error error) {
-                debug ("Failed to create a discoverer. Doing basic extraction.");
-                this.extract_basic_information (file, null, null);
+            return;
+        }
 
-                return;
-            }
-            this.file_hash.set (uri, file);
-            this.discoverer.discovered.connect (this.on_done);
-            this.discoverer.start ();
-            this.discoverer.discover_uri_async (uri);
-            this.guesser = new GUPnPDLNA.ProfileGuesser (true, true);
-        } else {
+        if (content_type == "application/x-cd-image") {
+            this.dvd_parser = new DVDParser (file);
+            this.dvd_parser.run.begin ();
+
+            return;
+        }
+
+        var uri = file.get_uri ();
+        try {
+            var gst_timeout = (ClockTime) (this.timeout * Gst.SECOND);
+
+            this.discoverer = new Discoverer (gst_timeout);
+        } catch (Error error) {
+            debug ("Failed to create a discoverer. Doing basic extraction.");
             this.extract_basic_information (file, null, null);
+
+            return;
         }
+
+        this.file_hash.set (uri, file);
+            this.discoverer.discovered.connect (this.on_done);
+        this.discoverer.start ();
+        this.discoverer.discover_uri_async (uri);
+        this.guesser = new GUPnPDLNA.ProfileGuesser (true, true);
     }
 
     private void on_done (DiscovererInfo info, GLib.Error err) {


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