[rygel/wip/media-engine: 9/9] WIP



commit 3ca8aecd816ba79d06f40c88d4ff4a578f1bab59
Author: Jens Georg <jensg openismus org>
Date:   Wed Sep 12 14:25:24 2012 +0200

    WIP

 common.am                                          |   11 +-
 configure.ac                                       |    2 +
 examples/standalone-server.c                       |   11 ++-
 src/Makefile.am                                    |    5 +-
 src/librygel-core/filelist.am                      |    1 +
 src/librygel-core/rygel-build-config.vapi          |    4 +-
 src/librygel-core/rygel-configuration.vala         |    2 +
 src/librygel-core/rygel-meta-config.vala           |   19 +++
 src/librygel-core/rygel-plugin-loader.vala         |   94 ++------------
 .../rygel-recursive-module-loader.vala             |  133 ++++++++++++++++++++
 src/librygel-renderer/Makefile.am                  |    7 +-
 src/librygel-server/filelist.am                    |   16 +--
 src/librygel-server/rygel-engine-loader.vala       |   46 +++++++
 src/librygel-server/rygel-http-byte-seek.vala      |    1 +
 src/librygel-server/rygel-http-seek.vala           |    6 +
 src/librygel-server/rygel-http-time-seek.vala      |    1 +
 src/librygel-server/rygel-media-engine.vala        |   14 ++-
 src/media-engines/Makefile.am                      |    1 +
 src/media-engines/gstreamer/Makefile.am            |   36 ++++++
 .../gstreamer}/rygel-aac-transcoder.vala           |    0
 .../gstreamer}/rygel-audio-transcoder.vala         |    0
 .../gstreamer}/rygel-avc-transcoder.vala           |    0
 .../gstreamer}/rygel-gst-data-source.vala          |    2 +-
 .../gstreamer}/rygel-gst-media-engine.vala         |   17 +++
 .../gstreamer}/rygel-gst-sink.vala                 |    2 +-
 .../gstreamer}/rygel-gst-transcoder.vala           |    0
 .../gstreamer}/rygel-gst-utils.vala                |    0
 .../gstreamer}/rygel-l16-transcoder.vala           |    0
 .../gstreamer}/rygel-mp2ts-transcoder.vala         |    0
 .../gstreamer}/rygel-mp3-transcoder.vala           |    0
 .../gstreamer}/rygel-video-transcoder.vala         |    0
 .../gstreamer}/rygel-wmv-transcoder.vala           |    0
 src/plugins/Makefile.am                            |    4 +-
 src/plugins/mpris/Makefile.am                      |    3 +-
 src/plugins/playbin/Makefile.am                    |    3 +-
 src/rygel/Makefile.am                              |    4 +
 src/rygel/rygel-cmdline-config.vala                |   14 ++-
 src/rygel/rygel-environment-config.vala            |    5 +
 src/rygel/rygel-main.vala                          |    8 +-
 src/rygel/rygel-user-config.vala                   |    5 +
 src/ui/Makefile.am                                 |    2 +-
 41 files changed, 352 insertions(+), 127 deletions(-)
---
diff --git a/common.am b/common.am
index 58512f7..6979fc6 100644
--- a/common.am
+++ b/common.am
@@ -3,6 +3,7 @@ shareddir = $(abs_top_builddir)/data
 sysconfigdir = $(shareddir)
 desktopdir = $(shareddir)
 plugindir = $(abs_top_builddir)/src/plugins
+enginedir = $(abs_top_builddir)/src/media-engines/gstreamer/.libs
 icondir = $(shareddir)/icons/32x32
 presetdir = $(shareddir)/presets
 
@@ -13,7 +14,8 @@ else
 shareddir = $(datadir)/rygel
 sysconfigdir = $(sysconfdir)
 desktopdir = $(datadir)/applications
-plugindir = $(libdir)/rygel-1.0
+plugindir = $(libdir)/rygel-1.0/plugins
+enginedir = $(libdir)/rygel-1.0/engines
 icondir = $(datadir)/icons/hicolor/32x32/apps
 presetdir = $(shareddir)/presets
 endif
@@ -31,8 +33,6 @@ MAINTAINERCLEANFILES = Makefile.in
 AM_CFLAGS = \
 	$(LIBGUPNP_CFLAGS) \
 	$(LIBGUPNP_AV_CFLAGS) \
-	$(LIBGSTREAMER_CFLAGS) \
-	$(GSTREAMER_BASE_CFLAGS) \
 	$(GEE_CFLAGS) \
 	$(UUID_CFLAGS) \
 	$(COVERAGE_CFLAGS) \
@@ -42,14 +42,12 @@ AM_CFLAGS = \
 	-I$(librygelrendererdir) \
 	-DDATA_DIR='"$(shareddir)"' -DSYS_CONFIG_DIR='"$(sysconfigdir)"'\
 	-DPLUGIN_DIR='"$(plugindir)"' -DDESKTOP_DIR='"$(desktopdir)"'\
-	-DPRESET_DIR='"$(presetdir)"'\
+	-DPRESET_DIR='"$(presetdir)"' -DENGINE_DIR='"$(enginedir)"' \
 	-include config.h
 
 RYGEL_BASE_LIBS = \
 	$(LIBGUPNP_LIBS) \
 	$(LIBGUPNP_AV_LIBS) \
-	$(LIBGSTREAMER_LIBS) \
-	$(GSTREAMER_BASE_LIBS) \
 	$(GEE_LIBS) \
 	$(UUID_LIBS) \
 	$(COVERAGE_LIBS)
@@ -66,6 +64,7 @@ RYGEL_COMMON_SERVER_LIBS = \
 
 RYGEL_COMMON_RENDERER_LIBS = \
 	$(top_builddir)/src/librygel-renderer/librygel-renderer-1.0.la \
+	$(LIBGSTREAMER_LIBS)
 	$(RYGEL_COMMON_LIBS)
 
 # Note: the -g needs to be at the end of VALAFLAGS to not break make dist
diff --git a/configure.ac b/configure.ac
index d7996a0..5f48fbf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -237,6 +237,8 @@ src/librygel-renderer/Makefile
 src/librygel-server/Makefile
 src/rygel/Makefile
 src/ui/Makefile
+src/media-engines/Makefile
+src/media-engines/gstreamer/Makefile
 src/plugins/Makefile
 data/Makefile
 data/xml/Makefile
diff --git a/examples/standalone-server.c b/examples/standalone-server.c
index 254b73f..98f9132 100644
--- a/examples/standalone-server.c
+++ b/examples/standalone-server.c
@@ -46,10 +46,19 @@ int main (int argc, char *argv[])
     GFileInfo *info;
     int i;
     GMainLoop *loop;
+    GError *error = NULL;
 
     g_type_init ();
 
-    gst_init (&argc, &argv);
+    rygel_media_engine_init (&error);
+
+    if (error != NULL) {
+        g_print ("Could not initialize media engine: %s\n",
+                 error->message);
+        g_error_free (error);
+
+        return EXIT_FAILURE;
+    }
 
     g_set_application_name ("Standalone-Server");
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 2426f6f..e18dcf3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,6 @@
+SUBDIRS = librygel-core librygel-renderer librygel-server rygel media-engines plugins
 if BUILD_UI
-SUBDIRS = librygel-core librygel-renderer librygel-server rygel ui plugins
-else
-SUBDIRS = librygel-core librygel-renderer librygel-server rygel plugins
+SUBDIRS += ui
 endif
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/librygel-core/filelist.am b/src/librygel-core/filelist.am
index a349072..2331754 100644
--- a/src/librygel-core/filelist.am
+++ b/src/librygel-core/filelist.am
@@ -7,6 +7,7 @@ LIBRYGEL_CORE_VAPI_SOURCE_FILES = \
 	rygel-log-handler.vala \
 	rygel-meta-config.vala \
 	rygel-plugin-loader.vala \
+	rygel-recursive-module-loader.vala \
 	rygel-plugin.vala \
 	rygel-resource-info.vala \
 	rygel-media-device.vala \
diff --git a/src/librygel-core/rygel-build-config.vapi b/src/librygel-core/rygel-build-config.vapi
index bbf0ceb..c393804 100644
--- a/src/librygel-core/rygel-build-config.vapi
+++ b/src/librygel-core/rygel-build-config.vapi
@@ -58,6 +58,6 @@ public class Rygel.BuildConfig {
     [CCode (cname = "LOCALEDIR")]
     public static const string LOCALEDIR;
 
-    [CCode (cname = "PRESET_DIR")]
-    public static const string PRESET_DIR;
+    [CCode (cname = "ENGINE_DIR")]
+    public static const string ENGINE_DIR;
 }
diff --git a/src/librygel-core/rygel-configuration.vala b/src/librygel-core/rygel-configuration.vala
index eeb5001..b25695f 100644
--- a/src/librygel-core/rygel-configuration.vala
+++ b/src/librygel-core/rygel-configuration.vala
@@ -49,6 +49,8 @@ public interface Rygel.Configuration : GLib.Object {
 
     public abstract string get_plugin_path () throws GLib.Error;
 
+    public abstract string get_engine_path () throws GLib.Error;
+
     public abstract string get_video_upload_folder () throws GLib.Error;
 
     public abstract string get_music_upload_folder () throws GLib.Error;
diff --git a/src/librygel-core/rygel-meta-config.vala b/src/librygel-core/rygel-meta-config.vala
index b695b3c..c99fe3e 100644
--- a/src/librygel-core/rygel-meta-config.vala
+++ b/src/librygel-core/rygel-meta-config.vala
@@ -210,6 +210,25 @@ public class Rygel.MetaConfig : GLib.Object, Configuration {
         return val;
     }
 
+    public string get_engine_path () throws GLib.Error {
+        string val = null;
+        bool unavailable = true;
+
+        foreach (var config in MetaConfig.configs) {
+            try {
+                val = config.get_engine_path ();
+                unavailable = false;
+                break;
+            } catch (GLib.Error err) {}
+        }
+
+        if (unavailable) {
+            throw new ConfigurationError.NO_VALUE_SET ("No value available");
+        }
+
+        return val;
+    }
+
     public string get_video_upload_folder () throws GLib.Error {
         unowned string default = Environment.get_user_special_dir
                                         (UserDirectory.VIDEOS);
diff --git a/src/librygel-core/rygel-plugin-loader.vala b/src/librygel-core/rygel-plugin-loader.vala
index a5569dc..385d04a 100644
--- a/src/librygel-core/rygel-plugin-loader.vala
+++ b/src/librygel-core/rygel-plugin-loader.vala
@@ -32,7 +32,7 @@ using Gee;
  * disabled by user using plugin_disabled method before creating the plugin
  * instance and resources related to that instance.
  */
-public class Rygel.PluginLoader : Object {
+public class Rygel.PluginLoader : RecursiveModuleLoader {
     private delegate void ModuleInitFunc (PluginLoader loader);
 
     private HashMap<string,Plugin> plugin_hash;
@@ -42,26 +42,16 @@ public class Rygel.PluginLoader : Object {
     public signal void plugin_available (Plugin plugin);
 
     public PluginLoader () {
-        this.plugin_hash = new HashMap<string,Plugin> (str_hash, str_equal);
-        this.loaded_modules = new HashSet<string> ();
-    }
-
-    // Plugin loading functions
-    public void load_plugins () {
-        assert (Module.supported());
-
-        string path;
+        var path = BuildConfig.PLUGIN_DIR;
         try {
             var config = MetaConfig.get_default ();
             path = config.get_plugin_path ();
-        } catch (Error error) {
-            path = BuildConfig.PLUGIN_DIR;
-        }
+        } catch (Error error) { }
 
-        File dir = File.new_for_path (path);
-        assert (dir != null && is_dir (dir));
+        base (path);
 
-        this.load_modules_from_dir.begin (dir);
+        this.plugin_hash = new HashMap<string,Plugin> (str_hash, str_equal);
+        this.loaded_modules = new HashSet<string> ();
     }
 
     /**
@@ -95,59 +85,12 @@ public class Rygel.PluginLoader : Object {
         return this.plugin_hash.values;
     }
 
-    private async void load_modules_from_dir (File dir) {
-        debug ("Searching for modules in folder '%s'.", dir.get_path ());
-
-        string attributes = FileAttribute.STANDARD_NAME + "," +
-                            FileAttribute.STANDARD_TYPE + "," +
-                            FileAttribute.STANDARD_CONTENT_TYPE;
-
-        GLib.List<FileInfo> infos;
-        FileEnumerator enumerator;
-
-        try {
-            enumerator = yield dir.enumerate_children_async
-                                        (attributes,
-                                         FileQueryInfoFlags.NONE,
-                                         Priority.DEFAULT,
-                                         null);
-
-            infos = yield enumerator.next_files_async (int.MAX,
-                                                       Priority.DEFAULT,
-                                                       null);
-        } catch (Error error) {
-            critical (_("Error listing contents of folder '%s': %s"),
-                      dir.get_path (),
-                      error.message);
-
-            return;
-        }
-
-        foreach (var info in infos) {
-            var file = dir.get_child (info.get_name ());
-            FileType file_type = info.get_file_type ();
-            string content_type = info.get_content_type ();
-            string mime = ContentType.get_mime_type (content_type);
-
-            if (file_type == FileType.DIRECTORY) {
-                // Recurse into directories
-                this.load_modules_from_dir.begin (file);
-            } else if (mime == "application/x-sharedlib") {
-                // Seems like we found a module
-                this.load_module_from_file (file);
-            }
-        }
-
-        debug ("Finished searching for modules in folder '%s'",
-               dir.get_path ());
-    }
-
-    private void load_module_from_file (File module_file) {
+    protected override bool load_module_from_file (File module_file) {
         if (module_file.get_basename () in this.loaded_modules) {
             warning (_("A module named %s is already loaded"),
                      module_file.get_basename ());
 
-            return;
+            return true;
         }
 
         Module module = Module.open (module_file.get_path (),
@@ -157,7 +100,7 @@ public class Rygel.PluginLoader : Object {
                      module_file.get_path (),
                      Module.error ());
 
-            return;
+            return true;
         }
 
         void* function;
@@ -168,7 +111,7 @@ public class Rygel.PluginLoader : Object {
                      module_file.get_path (),
                      Module.error ());
 
-            return;
+            return true;
         }
 
         unowned ModuleInitFunc module_init = (ModuleInitFunc) function;
@@ -181,22 +124,7 @@ public class Rygel.PluginLoader : Object {
         module_init (this);
 
         debug ("Loaded module source: '%s'", module.name());
-    }
-
-    private static bool is_dir (File file) {
-        FileInfo file_info;
-
-        try {
-            file_info = file.query_info (FileAttribute.STANDARD_TYPE,
-                                         FileQueryInfoFlags.NONE,
-                                         null);
-        } catch (Error error) {
-            critical (_("Failed to query content type for '%s'"),
-                      file.get_path ());
-
-            return false;
-        }
 
-        return file_info.get_file_type () == FileType.DIRECTORY;
+        return true;
     }
 }
diff --git a/src/librygel-core/rygel-recursive-module-loader.vala b/src/librygel-core/rygel-recursive-module-loader.vala
new file mode 100644
index 0000000..b7981b3
--- /dev/null
+++ b/src/librygel-core/rygel-recursive-module-loader.vala
@@ -0,0 +1,133 @@
+public abstract class Rygel.RecursiveModuleLoader : Object {
+    private static const string LOADER_ATTRIBUTES =
+                            FileAttribute.STANDARD_NAME + "," +
+                            FileAttribute.STANDARD_TYPE + "," +
+                            FileAttribute.STANDARD_CONTENT_TYPE;
+    private delegate void DirectoryHandler (File dir);
+
+    private string base_path;
+    private bool done;
+
+    public RecursiveModuleLoader (string path) {
+        this.base_path = path;
+        this.done = false;
+    }
+
+    // Plugin loading functions
+    public void load_modules () {
+        assert (Module.supported());
+
+        var dir = File.new_for_path (this.base_path);
+        assert (dir != null && this.is_dir (dir));
+
+        this.load_modules_from_dir.begin (dir);
+    }
+
+    public void load_modules_sync (Cancellable? cancellable = null) {
+        var queue = new Queue<File> ();
+
+        queue.push_head (File.new_for_path (this.base_path));
+        while (!queue.is_empty ()) {
+            var dir = queue.pop_head ();
+            try {
+                var enumerator = dir.enumerate_children
+                                        (LOADER_ATTRIBUTES,
+                                         FileQueryInfoFlags.NONE,
+                                         cancellable);
+                var info = enumerator.next_file (cancellable);
+                while (info != null) {
+                    this.handle_file_info (dir, info, (dir) => {
+                            queue.push_head (dir);
+                    });
+                    info = enumerator.next_file (cancellable);
+                }
+            } catch (Error error) {
+                debug ("Failed to enumerate directory %s: %s",
+                       dir.get_path (),
+                       error.message);
+            }
+        }
+    }
+
+    /**
+     * Load module from file.
+     * @param file File to load the module from
+     * @return The implementation should return true if the class should
+     * continue to search for modules, false otherwise.
+     */
+    protected abstract bool load_module_from_file (File file);
+
+    private async void load_modules_from_dir (File dir) {
+        debug ("Searching for modules in folder '%s'.", dir.get_path ());
+
+        GLib.List<FileInfo> infos;
+        FileEnumerator enumerator;
+
+        try {
+            enumerator = yield dir.enumerate_children_async
+                                        (LOADER_ATTRIBUTES,
+                                         FileQueryInfoFlags.NONE,
+                                         Priority.DEFAULT,
+                                         null);
+
+            infos = yield enumerator.next_files_async (int.MAX,
+                                                       Priority.DEFAULT,
+                                                       null);
+        } catch (Error error) {
+            critical (_("Error listing contents of folder '%s': %s"),
+                      dir.get_path (),
+                      error.message);
+
+            return;
+        }
+
+        foreach (var info in infos) {
+            if (this.done) {
+                break;
+            }
+
+            this.handle_file_info (dir, info, (subdir) => {
+                this.load_modules_from_dir.begin (subdir);
+            });
+        }
+
+        debug ("Finished searching for modules in folder '%s'",
+               dir.get_path ());
+    }
+
+    private void handle_file_info (File dir,
+                                  FileInfo info,
+                                  DirectoryHandler handler) {
+            var file = dir.get_child (info.get_name ());
+            FileType file_type = info.get_file_type ();
+            string content_type = info.get_content_type ();
+            string mime = ContentType.get_mime_type (content_type);
+
+            if (file_type == FileType.DIRECTORY) {
+                handler (file);
+            } else if (mime == "application/x-sharedlib") {
+                // Seems like we found a module
+                if (!this.load_module_from_file (file)) {
+                    this.done = true;
+                }
+            }
+
+    }
+
+    private bool is_dir (File file) {
+        FileInfo file_info;
+
+        try {
+            file_info = file.query_info (FileAttribute.STANDARD_TYPE,
+                                         FileQueryInfoFlags.NONE,
+                                         null);
+        } catch (Error error) {
+            critical (_("Failed to query content type for '%s'"),
+                      file.get_path ());
+
+            return false;
+        }
+
+        return file_info.get_file_type () == FileType.DIRECTORY;
+    }
+}
diff --git a/src/librygel-renderer/Makefile.am b/src/librygel-renderer/Makefile.am
index 0f40593..5b78773 100644
--- a/src/librygel-renderer/Makefile.am
+++ b/src/librygel-renderer/Makefile.am
@@ -9,10 +9,15 @@ librygel_renderer_1_0_la_SOURCES = \
 	$(LIBRYGEL_RENDERER_VAPI_SOURCE_FILES) \
 	$(LIBRYGEL_RENDERER_NONVAPI_SOURCE_FILES)
 
+librygel_renderer_1_0_la_CFLAGS = \
+	$(AM_CFLAGS) \
+	$(LIBGSTREAMER_CFLAGS)
+
 librygel_renderer_1_0_la_VALAFLAGS = \
 	-H rygel-renderer.h --library=rygel-renderer-1.0 \
+	--pkg gstreamer-0.10 \
 	$(RYGEL_COMMON_PLUGIN_VALAFLAGS)
-librygel_renderer_1_0_la_LIBADD = $(RYGEL_COMMON_LIBS)
+librygel_renderer_1_0_la_LIBADD = $(RYGEL_COMMON_LIBS) $(LIBGSTREAMER_LIBS)
 librygel_renderer_1_0_la_LDFLAGS = -version-info $(LIBRYGEL_RENDERER_VERSION)
 
 rygel-renderer.h rygel-renderer-1.0.vapi: librygel_renderer_1_0_la_vala.stamp
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am
index 2912d96..a389709 100644
--- a/src/librygel-server/filelist.am
+++ b/src/librygel-server/filelist.am
@@ -24,27 +24,23 @@ LIBRYGEL_SERVER_VAPI_SOURCE_FILES = \
 	rygel-writable-container.vala \
 	rygel-media-server.vala \
 	rygel-media-engine.vala \
+	rygel-http-seek.vala \
 	rygel-data-source.vala
 
 LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
-	rygel-aac-transcoder.vala \
-	rygel-audio-transcoder.vala \
-	rygel-avc-transcoder.vala \
 	rygel-browse.vala \
 	rygel-client-hacks.vala \
 	rygel-content-directory.vala \
 	rygel-dbus-thumbnailer.vala \
-	rygel-gst-utils.vala \
+    rygel-engine-loader.vala \
 	rygel-http-byte-seek.vala \
 	rygel-http-get-handler.vala \
 	rygel-http-get.vala \
-	rygel-gst-sink.vala \
 	rygel-http-identity-handler.vala \
 	rygel-http-item-uri.vala \
 	rygel-http-post.vala \
 	rygel-http-request.vala \
 	rygel-http-response.vala \
-	rygel-http-seek.vala \
 	rygel-http-server.vala \
 	rygel-http-time-seek.vala \
 	rygel-http-transcode-handler.vala \
@@ -52,11 +48,8 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
 	rygel-item-creator.vala \
 	rygel-item-destroyer.vala \
 	rygel-item-removal-queue.vala \
-	rygel-l16-transcoder.vala \
 	rygel-media-query-action.vala \
 	rygel-media-receiver-registrar.vala \
-	rygel-mp2ts-transcoder.vala \
-	rygel-mp3-transcoder.vala \
 	rygel-panasonic-hacks.vala \
 	rygel-search-criteria-parser.vala \
 	rygel-search.vala \
@@ -64,14 +57,9 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
 	rygel-subtitle-manager.vala \
 	rygel-thumbnailer.vala \
 	rygel-v1-hacks.vala \
-	rygel-video-transcoder.vala \
 	rygel-wmp-hacks.vala \
-	rygel-wmv-transcoder.vala \
 	rygel-xbmc-hacks.vala \
 	rygel-xbox-hacks.vala \
-	rygel-gst-media-engine.vala \
-	rygel-gst-transcoder.vala \
-	rygel-gst-data-source.vala \
 	rygel-data-sink.vala
 
 LIBRYGEL_SERVER_VALAFLAGS_PKG = \
diff --git a/src/librygel-server/rygel-engine-loader.vala b/src/librygel-server/rygel-engine-loader.vala
new file mode 100644
index 0000000..54b6768
--- /dev/null
+++ b/src/librygel-server/rygel-engine-loader.vala
@@ -0,0 +1,46 @@
+internal class Rygel.EngineLoader : RecursiveModuleLoader {
+    private delegate MediaEngine ModuleInstanceFunc ();
+    private MediaEngine instance;
+
+    public EngineLoader () {
+        var path = BuildConfig.ENGINE_DIR;
+        try {
+            var config = MetaConfig.get_default ();
+            path = config.get_engine_path ();
+        } catch (Error error) { }
+
+        base (path);
+    }
+
+    public MediaEngine load_engine () {
+        this.load_modules_sync ();
+
+        return instance;
+    }
+
+    protected override bool load_module_from_file (File file) {
+        var module = Module.open (file.get_path (),
+                                  ModuleFlags.BIND_LOCAL);
+        if (module == null) {
+            debug ("Failed to load engine %s: %s",
+                   file.get_path (),
+                   Module.error ());
+
+            return true;
+        }
+
+        void* function;
+        if (!module.symbol ("module_get_instance", out function)) {
+            //var message = _("Missing entry point in engine %s: %s");
+
+            return true;
+        }
+
+        unowned ModuleInstanceFunc get_instance =
+                                    (ModuleInstanceFunc) function;
+        module.make_resident ();
+        this.instance = get_instance ();
+
+        return false;
+    }
+}
diff --git a/src/librygel-server/rygel-http-byte-seek.vala b/src/librygel-server/rygel-http-byte-seek.vala
index 556ef75..4491b8d 100644
--- a/src/librygel-server/rygel-http-byte-seek.vala
+++ b/src/librygel-server/rygel-http-byte-seek.vala
@@ -55,6 +55,7 @@ internal class Rygel.HTTPByteSeek : Rygel.HTTPSeek {
         }
 
         base (request.msg, start, stop, 1, total_length);
+        this.seek_type = HTTPSeekType.BYTE;
     }
 
     public static bool needed (HTTPGet request) {
diff --git a/src/librygel-server/rygel-http-seek.vala b/src/librygel-server/rygel-http-seek.vala
index 670816b..7828601 100644
--- a/src/librygel-server/rygel-http-seek.vala
+++ b/src/librygel-server/rygel-http-seek.vala
@@ -28,7 +28,13 @@ public errordomain Rygel.HTTPSeekError {
     OUT_OF_RANGE = Soup.KnownStatusCode.REQUESTED_RANGE_NOT_SATISFIABLE,
 }
 
+public enum Rygel.HTTPSeekType {
+    BYTE,
+    TIME
+}
+
 public abstract class Rygel.HTTPSeek : GLib.Object {
+    public HTTPSeekType seek_type { get; protected set; }
     public Soup.Message msg { get; private set; }
 
     // These are either number of bytes or microseconds
diff --git a/src/librygel-server/rygel-http-time-seek.vala b/src/librygel-server/rygel-http-time-seek.vala
index 00cdbea..1cb42e5 100644
--- a/src/librygel-server/rygel-http-time-seek.vala
+++ b/src/librygel-server/rygel-http-time-seek.vala
@@ -86,6 +86,7 @@ internal class Rygel.HTTPTimeSeek : Rygel.HTTPSeek {
         }
 
         base (request.msg, start, stop, TimeSpan.MILLISECOND, duration);
+        this.seek_type = HTTPSeekType.TIME;
     }
 
     public static bool needed (HTTPGet request) {
diff --git a/src/librygel-server/rygel-media-engine.vala b/src/librygel-server/rygel-media-engine.vala
index 5bbe6c2..9181878 100644
--- a/src/librygel-server/rygel-media-engine.vala
+++ b/src/librygel-server/rygel-media-engine.vala
@@ -43,6 +43,10 @@ public class Rygel.DLNAProfile {
     }
 }
 
+public errordomain Rygel.MediaEngineError {
+    NOT_FOUND
+}
+
 /**
  * Base class for the media engine that will contain knowledge about streaming
  * and transcoding capabilites of the media library in use.
@@ -50,14 +54,20 @@ public class Rygel.DLNAProfile {
 public abstract class Rygel.MediaEngine : GLib.Object {
     private static MediaEngine instance;
 
+    public static void init () throws Error {
+        // lazy-load the engine plug-in
+        var loader = new EngineLoader ();
+        MediaEngine.instance = loader.load_engine ();
+    }
+
     /**
      * Get the singleton instance of the currently used media engine.
      *
-     * @return An instance of a concreate #MediaEngine implementation.
+     * @return An instance of a concrete #MediaEngine implementation.
      */
     public static MediaEngine get_default () {
         if (instance == null) {
-            instance = new GstMediaEngine ();
+            error (_("MediaEngine.init was not called. Cannot continue."));
         }
 
         return instance;
diff --git a/src/media-engines/Makefile.am b/src/media-engines/Makefile.am
new file mode 100644
index 0000000..7d0d842
--- /dev/null
+++ b/src/media-engines/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS=gstreamer
diff --git a/src/media-engines/gstreamer/Makefile.am b/src/media-engines/gstreamer/Makefile.am
new file mode 100644
index 0000000..996e2fb
--- /dev/null
+++ b/src/media-engines/gstreamer/Makefile.am
@@ -0,0 +1,36 @@
+include $(top_srcdir)/common.am
+
+engine_LTLIBRARIES = librygel-media-engine-gst.la
+
+AM_CFLAGS += -DG_LOG_DOMAIN='"MediaEngine-GStreamer"' \
+	$(GST_PBU_CFLAGS) \
+	$(LIBGUPNP_DLNA_CFLAGS)
+
+
+librygel_media_engine_gst_la_SOURCES = \
+	rygel-aac-transcoder.vala \
+	rygel-audio-transcoder.vala \
+	rygel-avc-transcoder.vala \
+	rygel-gst-data-source.vala \
+	rygel-gst-media-engine.vala \
+	rygel-gst-sink.vala \
+	rygel-gst-transcoder.vala \
+	rygel-gst-utils.vala \
+	rygel-l16-transcoder.vala \
+	rygel-mp2ts-transcoder.vala \
+	rygel-mp3-transcoder.vala \
+	rygel-video-transcoder.vala \
+	rygel-wmv-transcoder.vala
+
+librygel_media_engine_gst_la_VALAFLAGS = \
+	--pkg gstreamer-base-0.10 \
+	--pkg gstreamer-pbutils-0.10 \
+	--pkg gupnp-dlna-1.0 \
+	$(RYGEL_COMMON_SERVER_PLUGIN_VALAFLAGS)
+
+librygel_media_engine_gst_la_LIBADD = \
+	$(GST_PBU_LIBS) \
+	$(LIBGUPNP_DLNA_LIBS) \
+	$(RYGEL_COMMON_SERVER_LIBS)
+
+librygel_media_engine_gst_la_LDFLAGS = $(RYGEL_PLUGIN_LINKER_FLAGS)
diff --git a/src/librygel-server/rygel-aac-transcoder.vala b/src/media-engines/gstreamer/rygel-aac-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-aac-transcoder.vala
rename to src/media-engines/gstreamer/rygel-aac-transcoder.vala
diff --git a/src/librygel-server/rygel-audio-transcoder.vala b/src/media-engines/gstreamer/rygel-audio-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-audio-transcoder.vala
rename to src/media-engines/gstreamer/rygel-audio-transcoder.vala
diff --git a/src/librygel-server/rygel-avc-transcoder.vala b/src/media-engines/gstreamer/rygel-avc-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-avc-transcoder.vala
rename to src/media-engines/gstreamer/rygel-avc-transcoder.vala
diff --git a/src/librygel-server/rygel-gst-data-source.vala b/src/media-engines/gstreamer/rygel-gst-data-source.vala
similarity index 99%
rename from src/librygel-server/rygel-gst-data-source.vala
rename to src/media-engines/gstreamer/rygel-gst-data-source.vala
index 41cf91a..539a388 100644
--- a/src/librygel-server/rygel-gst-data-source.vala
+++ b/src/media-engines/gstreamer/rygel-gst-data-source.vala
@@ -200,7 +200,7 @@ public class Rygel.GstDataSource : Rygel.DataSource, GLib.Object {
         var flags = SeekFlags.FLUSH;
         int64 start, stop;
 
-        if (this.seek is HTTPTimeSeek) {
+        if (this.seek.seek_type == HTTPSeekType.TIME) {
             format = Format.TIME;
             flags |= SeekFlags.KEY_UNIT;
             start = (this.seek.start) * Gst.USECOND;
diff --git a/src/librygel-server/rygel-gst-media-engine.vala b/src/media-engines/gstreamer/rygel-gst-media-engine.vala
similarity index 88%
rename from src/librygel-server/rygel-gst-media-engine.vala
rename to src/media-engines/gstreamer/rygel-gst-media-engine.vala
index 890de4c..fe09d9e 100644
--- a/src/librygel-server/rygel-gst-media-engine.vala
+++ b/src/media-engines/gstreamer/rygel-gst-media-engine.vala
@@ -23,11 +23,24 @@
 using Gst;
 using Gee;
 
+// Remove for GStreamer 1.0
+[CCode (cname = "PRESET_DIR")]
+internal extern static const string PRESET_DIR;
+
+[CCode (cname="gst_preset_set_app_dir")]
+extern bool gst_preset_set_app_dir (string app_dir);
+
 internal class Rygel.GstMediaEngine : Rygel.MediaEngine {
     private GLib.List<DLNAProfile> dlna_profiles = null;
     private GLib.List<Transcoder> transcoders = null;
 
     public GstMediaEngine () {
+        // Work-around vapi bug, fixed for GStreamer 1.0
+        unowned string[] args = null;
+
+        Gst.init (ref args);
+        gst_preset_set_app_dir (PRESET_DIR);
+
         var discoverer = new GUPnP.DLNADiscoverer ((ClockTime) SECOND,
                                                    true,
                                                    false);
@@ -92,3 +105,7 @@ internal class Rygel.GstMediaEngine : Rygel.MediaEngine {
         return new GstDataSource (uri);
     }
 }
+
+public static Rygel.MediaEngine module_get_instance () {
+    return new Rygel.GstMediaEngine ();
+}
diff --git a/src/librygel-server/rygel-gst-sink.vala b/src/media-engines/gstreamer/rygel-gst-sink.vala
similarity index 98%
rename from src/librygel-server/rygel-gst-sink.vala
rename to src/media-engines/gstreamer/rygel-gst-sink.vala
index eed08d0..690977e 100644
--- a/src/librygel-server/rygel-gst-sink.vala
+++ b/src/media-engines/gstreamer/rygel-gst-sink.vala
@@ -70,7 +70,7 @@ internal class Rygel.GstSink : BaseSink {
         this.frozen = false;
 
         if (this.offsets != null) {
-            if (this.offsets is HTTPByteSeek) {
+            if (this.offsets.seek_type == HTTPSeekType.BYTE) {
                 this.max_bytes = this.offsets.length;
             }
         }
diff --git a/src/librygel-server/rygel-gst-transcoder.vala b/src/media-engines/gstreamer/rygel-gst-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-gst-transcoder.vala
rename to src/media-engines/gstreamer/rygel-gst-transcoder.vala
diff --git a/src/librygel-server/rygel-gst-utils.vala b/src/media-engines/gstreamer/rygel-gst-utils.vala
similarity index 100%
rename from src/librygel-server/rygel-gst-utils.vala
rename to src/media-engines/gstreamer/rygel-gst-utils.vala
diff --git a/src/librygel-server/rygel-l16-transcoder.vala b/src/media-engines/gstreamer/rygel-l16-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-l16-transcoder.vala
rename to src/media-engines/gstreamer/rygel-l16-transcoder.vala
diff --git a/src/librygel-server/rygel-mp2ts-transcoder.vala b/src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-mp2ts-transcoder.vala
rename to src/media-engines/gstreamer/rygel-mp2ts-transcoder.vala
diff --git a/src/librygel-server/rygel-mp3-transcoder.vala b/src/media-engines/gstreamer/rygel-mp3-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-mp3-transcoder.vala
rename to src/media-engines/gstreamer/rygel-mp3-transcoder.vala
diff --git a/src/librygel-server/rygel-video-transcoder.vala b/src/media-engines/gstreamer/rygel-video-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-video-transcoder.vala
rename to src/media-engines/gstreamer/rygel-video-transcoder.vala
diff --git a/src/librygel-server/rygel-wmv-transcoder.vala b/src/media-engines/gstreamer/rygel-wmv-transcoder.vala
similarity index 100%
rename from src/librygel-server/rygel-wmv-transcoder.vala
rename to src/media-engines/gstreamer/rygel-wmv-transcoder.vala
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 747d837..6d07b18 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,5 +1,5 @@
 if BUILD_TEST_PLUGIN
-TEST_PLUGIN = test
+#TEST_PLUGIN = test
 endif
 
 if BUILD_TRACKER_PLUGIN
@@ -23,7 +23,7 @@ MPRIS_PLUGIN = mpris
 endif
 
 if BUILD_GST_LAUNCH_PLUGIN
-GST_LAUNCH_PLUGIN = gst-launch
+#GST_LAUNCH_PLUGIN = gst-launch
 endif
 
 if BUILD_PLAYBIN_PLUGIN
diff --git a/src/plugins/mpris/Makefile.am b/src/plugins/mpris/Makefile.am
index 4b609de..b108c38 100644
--- a/src/plugins/mpris/Makefile.am
+++ b/src/plugins/mpris/Makefile.am
@@ -2,7 +2,8 @@ include ../../../common.am
 
 plugin_LTLIBRARIES = librygel-mpris.la
 
-AM_CFLAGS += -DG_LOG_DOMAIN='"MPRIS"'
+AM_CFLAGS += -DG_LOG_DOMAIN='"MPRIS"' \
+	$(LIBGSTREAMER_CFLAGS)
 
 librygel_mpris_la_SOURCES = \
 	rygel-mpris-player.vala \
diff --git a/src/plugins/playbin/Makefile.am b/src/plugins/playbin/Makefile.am
index 734056c..3a53300 100644
--- a/src/plugins/playbin/Makefile.am
+++ b/src/plugins/playbin/Makefile.am
@@ -2,7 +2,8 @@ include ../../../common.am
 
 plugin_LTLIBRARIES = librygel-playbin.la
 
-AM_CFLAGS += -DG_LOG_DOMAIN='"Playbin"'
+AM_CFLAGS += -DG_LOG_DOMAIN='"Playbin"' \
+	$(LIBGSTREAMER_CFLAGS)
 
 librygel_playbin_la_SOURCES = rygel-module.vala
 librygel_playbin_la_CFLAGS = $(AM_CFLAGS)
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index d2ceb4f..75c3f6e 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -22,10 +22,14 @@ rygel_SOURCES = \
 rygel_VALAFLAGS = \
 	--pkg posix \
 	--pkg gstreamer-0.10 \
+	--pkg rygel-server-1.0 \
+	--vapidir $(top_srcdir)/src/librygel-server \
 	$(RYGEL_COMMON_VALAFLAGS)
 
 rygel_LDADD = \
 	$(top_builddir)/src/librygel-core/librygel-core-1.0.la \
+	$(top_builddir)/src/librygel-server/librygel-server-1.0.la \
+	$(LIBGSTREAMER_LIBS) \
 	$(RYGEL_BASE_LIBS)
 
 rygel_LDFLAGS = -export-dynamic
diff --git a/src/rygel/rygel-cmdline-config.vala b/src/rygel/rygel-cmdline-config.vala
index ea00324..2c70379 100644
--- a/src/rygel/rygel-cmdline-config.vala
+++ b/src/rygel/rygel-cmdline-config.vala
@@ -46,6 +46,7 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
     private static string log_levels;
 
     private static string plugin_path;
+    private static string engine_path;
 
     private static bool version;
 
@@ -87,6 +88,8 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
           "DOMAIN1:LEVEL1[,DOMAIN2:LEVEL2,..]" },
         { "plugin-path", 'u', 0, OptionArg.STRING, ref plugin_path,
           "Plugin Path", "PLUGIN_PATH" },
+        { "engine-path", 'e', 0, OptionArg.STRING, ref engine_path,
+          "Engine Path", "ENGINE_PATH" },
         { "disable-plugin", 'd', 0, OptionArg.STRING_ARRAY,
           ref disabled_plugins,
           "Disable plugin", "PluginName" },
@@ -117,7 +120,6 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
         opt_context.set_help_enabled (true);
         opt_context.set_ignore_unknown_options (true);
         opt_context.add_main_entries (options, null);
-        opt_context.add_group (Gst.init_get_option_group ());
 
         try {
             opt_context.parse (ref args);
@@ -198,7 +200,15 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
         return plugin_path;
     }
 
-    public bool get_enabled (string section) throws GLib.Error {
+    public string get_engine_path () throws GLib.Error {
+        if (engine_path == null) {
+            throw new ConfigurationError.NO_VALUE_SET ("No value available");
+        }
+
+        return plugin_path;
+    }
+
+   public bool get_enabled (string section) throws GLib.Error {
         var disabled = false;
         foreach (var plugin in disabled_plugins) {
             if (plugin == section) {
diff --git a/src/rygel/rygel-environment-config.vala b/src/rygel/rygel-environment-config.vala
index 75d7d1f..518b389 100644
--- a/src/rygel/rygel-environment-config.vala
+++ b/src/rygel/rygel-environment-config.vala
@@ -42,6 +42,7 @@ internal class Rygel.EnvironmentConfig : GLib.Object, Configuration {
     private static string DISALLOW_DELETION_ENV = DISABLE_PREFIX + "_DELETION";
     private static string LOG_LEVELS_ENV = RYGEL_PREFIX + "_LOG";
     private static string PLUGIN_PATH_ENV = RYGEL_PREFIX + "_PLUGIN_PATH";
+    private static string ENGINE_PATH_ENV = RYGEL_PREFIX + "_ENGINE_PATH";
 
     // Our singleton
     private static EnvironmentConfig config;
@@ -86,6 +87,10 @@ internal class Rygel.EnvironmentConfig : GLib.Object, Configuration {
         return this.get_string_variable (PLUGIN_PATH_ENV);
     }
 
+    public string get_engine_path () throws GLib.Error {
+        return this.get_string_variable (ENGINE_PATH_ENV);
+    }
+
     public string get_video_upload_folder () throws GLib.Error {
         throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
     }
diff --git a/src/rygel/rygel-main.vala b/src/rygel/rygel-main.vala
index 8207d82..6d9c218 100644
--- a/src/rygel/rygel-main.vala
+++ b/src/rygel/rygel-main.vala
@@ -27,9 +27,6 @@ using Gee;
 using GUPnP;
 using Posix;
 
-[CCode (cname="gst_preset_set_app_dir")]
-extern bool gst_preset_set_app_dir (string app_dir);
-
 internal class Rygel.Main : Object {
     private static int PLUGIN_TIMEOUT = 5;
 
@@ -64,8 +61,6 @@ internal class Rygel.Main : Object {
         Unix.signal_add (SIGHUP, () => { this.restart (); return true; });
         Unix.signal_add (SIGINT, () => { this.exit (0); return false; });
         Unix.signal_add (SIGTERM, () => { this.exit (0); return false; });
-
-        gst_preset_set_app_dir (BuildConfig.PRESET_DIR);
     }
 
     public void exit (int exit_code) {
@@ -89,7 +84,7 @@ internal class Rygel.Main : Object {
 
     internal void dbus_available () {
         this.context_manager = this.create_context_manager ();
-        this.plugin_loader.load_plugins ();
+        this.plugin_loader.load_modules ();
 
         var timeout = PLUGIN_TIMEOUT;
         try {
@@ -280,6 +275,7 @@ internal class Rygel.Main : Object {
             // Parse commandline options
             CmdlineConfig.parse_args (ref args);
             Main.register_default_configurations ();
+            MediaEngine.init ();
 
             main = new Main ();
             service = new DBusService (main);
diff --git a/src/rygel/rygel-user-config.vala b/src/rygel/rygel-user-config.vala
index 26f5b5a..b918ec1 100644
--- a/src/rygel/rygel-user-config.vala
+++ b/src/rygel/rygel-user-config.vala
@@ -41,6 +41,7 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
     public static const string ALLOW_DELETION_KEY = "allow-deletion";
     public static const string LOG_LEVELS_KEY = "log-level";
     public static const string PLUGIN_PATH_KEY = "plugin-path";
+    public static const string ENGINE_PATH_KEY = "engine-path";
     public static const string UPLOAD_FOLDER_KEY = "upload-folder";
     public static const string VIDEO_UPLOAD_DIR_PATH_KEY =
                                         "video-" + UPLOAD_FOLDER_KEY;
@@ -87,6 +88,10 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
         return this.get_string ("general", PLUGIN_PATH_KEY);
     }
 
+    public string get_engine_path () throws GLib.Error {
+        return this.get_string ("general", PLUGIN_PATH_KEY);
+    }
+
     public string get_video_upload_folder () throws GLib.Error {
         return this.get_string ("general", VIDEO_UPLOAD_DIR_PATH_KEY);
     }
diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am
index a5ad827..06cc965 100644
--- a/src/ui/Makefile.am
+++ b/src/ui/Makefile.am
@@ -16,7 +16,7 @@ rygel_preferences_SOURCES =  \
 	rygel-user-config.vala
 
 rygel_preferences_VALAFLAGS = \
-	--thread --pkg gio-2.0 \
+	--pkg gio-2.0 \
 	--pkg gtk+-3.0 $(RYGEL_COMMON_PLUGIN_VALAFLAGS)
 
 rygel_preferences_LDADD = \



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