[rygel/wip/media-engine: 16/17] engine: Add a sample media engine implementation



commit 08d4e400d1fde553d5d16cdc2e6b35fee69f79d5
Author: Jens Georg <jensg openismus com>
Date:   Fri Oct 5 09:26:28 2012 +0200

    engine: Add a sample media engine implementation

 configure.ac                                       |    7 +
 src/media-engines/Makefile.am                      |    2 +-
 src/media-engines/simple/Makefile.am               |   15 ++
 .../simple/rygel-simple-data-source.vala           |  151 ++++++++++++++++++++
 .../simple/rygel-simple-media-engine.vala          |   43 ++++++
 5 files changed, 217 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4e73b43..7c5e327 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,8 @@ PKG_CHECK_MODULES(UUID, uuid >= $UUID_REQUIRED)
 PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4 >= $LIBSOUP_REQUIRED)
 
 dnl Media engine to use
+BUILT_ENGINES="librygel-media-engine-simple"
+
 AC_ARG_WITH([media_engine],
             AS_HELP_STRING(
                 [--with-media-engine=@<:@gstreamer|none@:>@],
@@ -78,9 +80,11 @@ AS_IF([test "x$with_media_engine" = "xgstreamer"],
         PKG_CHECK_MODULES(GSTREAMER_BASE, gstreamer-base-0.10 >= $GSTREAMER_REQUIRED)
         PKG_CHECK_MODULES(GST_PBU, gstreamer-pbutils-0.10 >= $GSTPBU_REQUIRED)
         enable_gstreamer="yes"
+        BUILT_ENGINES="$BUILT_ENGINES;librygel-media-engine-gst"
       ],
       [enable_gstreamer="no"])
 AM_CONDITIONAL([HAVE_GSTREAMER],[test "x$enable_gstreamer" = "xyes"])
+AC_SUBST([BUILT_ENGINES])
 
 dnl Add plugins
 RYGEL_ADD_PLUGIN([external],[MediaServer2 DBus consumer],[yes])
@@ -94,6 +98,7 @@ AS_IF([test "x$with_media_engine" = "xgstreamer"],
         RYGEL_ADD_PLUGIN([playbin],[GStreamer playbin],[yes])
         RYGEL_ADD_PLUGIN([media-export],[MediaExport],[yes])
         RYGEL_ADD_PLUGIN([gst-launch],[GStreamer launchline],[no])
+        RYGEL_ADD_STAMP([src/media-engines/gstreamer/librygel_media_engine_gst_la_vala.stamp])
       ],
       [
         RYGEL_DISABLE_PLUGIN([test])
@@ -108,6 +113,7 @@ RYGEL_ADD_STAMP([src/librygel-server/librygel_server_1_0_la_vala.stamp])
 RYGEL_ADD_STAMP([src/librygel-renderer/librygel_renderer_1_0_la_vala.stamp])
 RYGEL_ADD_STAMP([src/rygel/rygel_vala.stamp])
 RYGEL_ADD_STAMP([src/ui/rygel_preferences_vala.stamp])
+RYGEL_ADD_STAMP([src/media-engines/simple/librygel_media_engine_simple_la_vala.stamp])
 
 RYGEL_CHECK_VALA([$VALA_REQUIRED],
                  [gupnp-1.0
@@ -270,6 +276,7 @@ src/rygel/Makefile
 src/ui/Makefile
 src/media-engines/Makefile
 src/media-engines/gstreamer/Makefile
+src/media-engines/simple/Makefile
 src/plugins/Makefile
 data/Makefile
 data/xml/Makefile
diff --git a/src/media-engines/Makefile.am b/src/media-engines/Makefile.am
index 9cf45e9..ed2f101 100644
--- a/src/media-engines/Makefile.am
+++ b/src/media-engines/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=
+SUBDIRS=simple
 
 if HAVE_GSTREAMER
 SUBDIRS += gstreamer
diff --git a/src/media-engines/simple/Makefile.am b/src/media-engines/simple/Makefile.am
new file mode 100644
index 0000000..039a892
--- /dev/null
+++ b/src/media-engines/simple/Makefile.am
@@ -0,0 +1,15 @@
+include $(top_srcdir)/common.am
+
+engine_LTLIBRARIES = librygel-media-engine-simple.la
+
+AM_CFLAGS += -DG_LOG_DOMAIN='"MediaEngine-Simple"'
+
+librygel_media_engine_simple_la_SOURCES = \
+	rygel-simple-media-engine.vala \
+	rygel-simple-data-source.vala
+
+librygel_media_engine_simple_la_VALAFLAGS = \
+	$(RYGEL_COMMON_SERVER_PLUGIN_VALAFLAGS)
+
+librygel_media_engine_simple_la_LIBADD = $(RYGEL_COMMON_SERVER_LIBS)
+librygel_media_engine_simple_la_LDFLAGS = $(RYGEL_PLUGIN_LINKER_FLAGS)
diff --git a/src/media-engines/simple/rygel-simple-data-source.vala b/src/media-engines/simple/rygel-simple-data-source.vala
new file mode 100644
index 0000000..b578002
--- /dev/null
+++ b/src/media-engines/simple/rygel-simple-data-source.vala
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+internal class Rygel.SimpleDataSource : DataSource, Object {
+    private string uri;
+    private Thread<void*> thread;
+    private Mutex mutex = Mutex ();
+    private Cond cond = Cond ();
+    private uint64 first_byte = 0;
+    private uint64 last_byte = 0;
+    private bool frozen = false;
+    private bool stop_thread = false;
+    private HTTPSeek offsets = null;
+
+    public SimpleDataSource (string uri) {
+        debug ("Creating new data source for %s", uri);
+        this.uri = uri;
+    }
+
+    ~SimpleDataSource () {
+        this.stop ();
+    }
+
+    public void start (HTTPSeek? offsets) throws Error {
+        if (offsets != null) {
+            if (offsets.seek_type == HTTPSeekType.TIME) {
+                throw new DataSourceError.SEEK_FAILED
+                                        (_("Time-based seek not supported"));
+
+            }
+        }
+
+        this.offsets = offsets;
+
+        debug ("Starting data source for uri %s", this.uri);
+
+        // TODO: Convert to use a thread pool
+        this.thread = new Thread<void*> ("Rygel Serving thread",
+                                         this.thread_func);
+    }
+
+    public void freeze () {
+        if (this.frozen) {
+            return;
+        }
+
+        this.mutex.lock ();
+        this.frozen = true;
+        this.mutex.unlock ();
+    }
+
+    public void thaw () {
+        if (!this.frozen) {
+            return;
+        }
+
+        this.mutex.lock ();
+        this.frozen = false;
+        this.cond.broadcast ();
+        this.mutex.unlock ();
+    }
+
+    public void stop () {
+        if (this.stop_thread) {
+            return;
+        }
+
+        this.mutex.lock ();
+        this.frozen = false;
+        this.stop_thread = true;
+        this.cond.broadcast ();
+        this.mutex.unlock ();
+    }
+
+    private void* thread_func () {
+        var file = File.new_for_commandline_arg (this.uri);
+        debug ("Spawning new thread for streaming file %s", this.uri);
+        try {
+            var mapped = new MappedFile (file.get_path (), false);
+            if (this.offsets != null) {
+                this.first_byte = this.offsets.start;
+                this.last_byte = this.offsets.stop + 1;
+            } else {
+                this.last_byte = mapped.get_length ();
+            }
+
+            while (true) {
+                bool exit;
+                this.mutex.lock ();
+                while (this.frozen) {
+                    this.cond.wait (this.mutex);
+                }
+
+                exit = this.stop_thread;
+                this.mutex.unlock ();
+
+                if (exit || this.first_byte == this.last_byte) {
+                    debug ("Done streaming!");
+
+                    break;
+                }
+
+                var start = this.first_byte;
+                var stop = start + uint16.MAX;
+                if (stop > this.last_byte) {
+                    stop = this.last_byte;
+                }
+
+                unowned uint8[] data = (uint8[]) mapped.get_contents ();
+                data.length = (int) mapped.get_length ();
+                uint8[] slice = data[start:stop];
+                this.first_byte = stop;
+
+                // There's a potential race condition here.
+                Idle.add ( () => {
+                    if (!this.stop_thread) {
+                        this.data_available (slice);
+                    }
+
+                    return false;
+                });
+            }
+        } catch (Error error) {
+            warning ("Failed to map file: %s", error.message);
+        }
+
+        // signalize we're done streaming
+        Idle.add ( () => { this.done (); return false; });
+
+        return null;
+    }
+}
diff --git a/src/media-engines/simple/rygel-simple-media-engine.vala b/src/media-engines/simple/rygel-simple-media-engine.vala
new file mode 100644
index 0000000..c26faed
--- /dev/null
+++ b/src/media-engines/simple/rygel-simple-media-engine.vala
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+internal class Rygel.SimpleMediaEngine : MediaEngine {
+    private List<DLNAProfile> profiles = new List<DLNAProfile> ();
+
+    public SimpleMediaEngine () { }
+
+    public override unowned List<DLNAProfile> get_dlna_profiles () {
+        return this.profiles;
+    }
+
+    public override unowned List<Transcoder>? get_transcoders () {
+        return null;
+    }
+
+    public override DataSource create_data_source (string uri) {
+        return new SimpleDataSource (uri);
+    }
+}
+
+public static Rygel.MediaEngine module_get_instance () {
+    return new Rygel.SimpleMediaEngine ();
+}



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