[totem] Port to libpeas for plugin handling



commit 7bf399f1365f8e9f76edb08007b10a9c756f650b
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Jun 15 17:10:52 2010 +0100

    Port to libpeas for plugin handling
    
    https://bugzilla.gnome.org/show_bug.cgi?id=604830

 .gitignore                                         |    1 +
 bindings/python/Makefile.am                        |   24 +-
 bindings/python/__init__.py                        |   50 ++
 bindings/python/override_common.c                  |    2 +-
 bindings/python/totem.defs                         |   70 +--
 bindings/python/totem.override                     |   47 +-
 bindings/python/totemmodule.c                      |  230 ++++++
 bindings/vala/totem.vapi                           |    2 +-
 configure.in                                       |   19 +-
 docs/reference/Makefile.am                         |    3 +-
 src/Makefile.am                                    |   21 +-
 src/plugins/Makefile.am                            |   42 +-
 src/plugins/totem-dirs.c                           |  182 +++++
 .../{totem-python-plugin.h => totem-dirs.h}        |   43 +-
 src/plugins/totem-module.c                         |  173 ----
 src/plugins/totem-module.h                         |   56 --
 src/plugins/totem-plugin-manager.c                 |  533 ------------
 src/plugins/totem-plugin-manager.h                 |   78 --
 src/plugins/totem-plugins-engine.c                 |  845 +++++---------------
 src/plugins/totem-plugins-engine.h                 |   48 +-
 src/plugins/totem-python-module.c                  |  566 -------------
 src/plugins/totem-python-module.h                  |   61 --
 src/plugins/totem-python-plugin.c                  |  282 -------
 src/plugins/totem/Makefile.am                      |    4 -
 src/plugins/totem/__init__.py                      |    6 -
 src/plugins/tracker/Makefile.am                    |    1 +
 src/plugins/tracker/totem-tracker.c                |   15 +-
 src/plugins/youtube/Makefile.am                    |    1 +
 src/plugins/youtube/totem-youtube.c                |   14 +-
 src/totem-interface.c                              |    4 +-
 src/totem-interface.h                              |    3 +-
 src/totem-menu.c                                   |    4 +-
 src/totem-object.c                                 |   14 +-
 src/totem-private.h                                |    2 +
 src/totem.h                                        |    2 +-
 35 files changed, 805 insertions(+), 2643 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 5646fde..64429a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ stamp*
 *.gmo
 *.mo
 *.omf
+*.totem-plugin
 .deps
 .libs
 
diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am
index ab6077d..abb7e4f 100644
--- a/bindings/python/Makefile.am
+++ b/bindings/python/Makefile.am
@@ -1,33 +1,41 @@
 ## Process this file with automake to produce Makefile.in
 
-noinst_LTLIBRARIES = totem-python.la
+plugindir = $(PLUGINDIR)/python/totem
+plugin_PYTHON = __init__.py
 
-nodist_totem_python_la_SOURCES = totem.c
+pymoduledir = $(libdir)/totem/plugins/python/totem
+pymodule_LTLIBRARIES = _totem.la
 
-totem_python_la_SOURCES = override_common.c override_common.h
+nodist__totem_la_SOURCES = totem.c
 
-totem_python_la_LDFLAGS = \
-	-module -avoid-version
+_totem_la_SOURCES = override_common.c override_common.h totemmodule.c
 
-totem_python_la_LIBADD = \
+_totem_la_LDFLAGS = \
+	-module -avoid-version \
+	-export-symbol-regex init_totem
+
+_totem_la_LIBADD = \
 	$(DEPENDENCY_LIBS)	\
 	$(PYTHON_LIBS)		\
 	$(PYTHON_EXTRA_LIBS)	\
 	$(PYGTK_LIBS)
 
-totem_python_la_CFLAGS = \
+_totem_la_CFLAGS = \
 	-I$(top_srcdir)			\
 	-I$(top_srcdir)/src		\
 	-I$(top_srcdir)/src/plugins	\
 	$(DEPENDENCY_CFLAGS)		\
+	$(PEAS_CFLAGS)			\
 	$(PYGTK_CFLAGS)			\
 	$(PYTHON_CFLAGS)		\
 	$(AM_CFLAGS)			\
-	$(WNOERROR_CFLAGS)
+	$(WNOERROR_CFLAGS)		\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"
 
 totem.c: totem.defs totem.override
 	( cd $(srcdir) && $(PYGTK_CODEGEN) \
 		--register $(PYGTK_DEFSDIR)/gtk-types.defs \
+		--register $(PYGTK_DEFSDIR)/libpeas.defs \
 		--override $*.override \
 		--prefix py$* $(<F) ) > $@ 
 
diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py
new file mode 100644
index 0000000..4933c72
--- /dev/null
+++ b/bindings/python/__init__.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# ex:set ts=4 et sw=4 ai:
+#
+#    Totem Python bindings
+#    Copyright (C) 2009  Steve Frécinaux
+#
+#    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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+# Import everything from the binary module
+from totem._totem import *
+
+import gobject
+from totem import _totem
+
+def _method_is_overriden(plugin, method_name):
+    child_method = getattr(plugin.__class__, method_name, None)
+    parent_method = getattr(_totem.Plugin, method_name, None)
+    return child_method != parent_method
+
+def _proxy_plugin_method(method_name):
+    def method(self, window):
+        if _method_is_overriden(self, method_name):
+            return getattr(self, method_name)(window)
+    return method
+
+class Plugin(_totem.Plugin):
+    do_activate = _proxy_plugin_method('activate')
+    do_deactivate = _proxy_plugin_method('deactivate')
+    do_update_ui = _proxy_plugin_method('update_ui')
+
+    def do_is_configurable(self):
+        return _method_is_overriden(self, 'create_configure_dialog')
+
+    def do_create_configure_dialog(self):
+        if _method_is_overriden(self, 'create_configure_dialog'):
+            return self.create_configure_dialog()
+
+gobject.type_register(Plugin)
diff --git a/bindings/python/override_common.c b/bindings/python/override_common.c
index 99931e7..719f5e4 100644
--- a/bindings/python/override_common.c
+++ b/bindings/python/override_common.c
@@ -28,7 +28,7 @@
 
 #include "config.h"
 
-#define NO_IMPORT_PYGOBJECT
+//#define NO_IMPORT_PYGOBJECT
 #include "pygobject.h"
 #include <pygtk/pygtk.h>
 
diff --git a/bindings/python/totem.defs b/bindings/python/totem.defs
index ade52e5..fd90c3d 100644
--- a/bindings/python/totem.defs
+++ b/bindings/python/totem.defs
@@ -3,11 +3,21 @@
 
 (define-object Plugin
   (in-module "Totem")
-  (parent "GObject")
+  (parent "PeasPlugin")
   (c-name "TotemPlugin")
   (gtype-id "TOTEM_TYPE_PLUGIN")
 )
 
+(define-virtual is_configurable
+  (of-object "TotemPlugin")
+  (return-type "gboolean")
+)
+
+(define-virtual create_configure_dialog
+  (of-object "TotemPlugin")
+  (return-type "GtkWidget*")
+)
+
 (define-object Object
   (in-module "Totem")
   (parent "GObject")
@@ -45,15 +55,6 @@
   )
 )
 
-(define-enum PluginError
-  (in-module "Totem")
-  (c-name "TotemPluginError")
-  (gtype-id "TOTEM_TYPE_PLUGIN_ERROR")
-  (values
-    '("n" "TOTEM_PLUGIN_ERROR_ACTIVATION")
-  )
-)
-
 (define-enum RemoteCommand
   (in-module "Totem")
   (c-name "TotemRemoteCommand")
@@ -105,49 +106,9 @@
 
 ;; From totem-plugin.h
 
-(define-function totem_plugin_error_quark
-  (c-name "totem_plugin_error_quark")
-  (return-type "GQuark")
-)
-
-(define-method activate
-  (of-object "TotemPlugin")
-  (c-name "totem_plugin_activate")
-  (return-type "gboolean")
-  (parameters
-    '("TotemObject*" "totem")
-    '("GError**" "error")
-  )
-)
-
-(define-method deactivate
-  (of-object "TotemPlugin")
-  (c-name "totem_plugin_deactivate")
-  (return-type "none")
-  (parameters
-    '("TotemObject*" "totem")
-  )
-)
-
-(define-method is_configurable
-  (of-object "TotemPlugin")
-  (c-name "totem_plugin_is_configurable")
-  (return-type "gboolean")
-)
-
-(define-method create_configure_dialog
-  (of-object "TotemPlugin")
-  (c-name "totem_plugin_create_configure_dialog")
-  (return-type "GtkWidget*")
-)
-
-(define-method find_file
-  (of-object "TotemPlugin")
-  (c-name "totem_plugin_find_file")
-  (return-type "char*")
-  (parameters
-    '("const-char*" "file")
-  )
+(define-function totem_plugin_get_type
+  (c-name "totem_plugin_get_type")
+  (return-type "GType")
 )
 
 (define-method load_interface
@@ -162,7 +123,6 @@
   )
 )
 
-
 ;; From totem.h
 
 (define-method plugins_init
@@ -553,7 +513,7 @@
     '("const-char*" "reason")
     '("const-char*" "uri")
     '("const-char*" "label")
-    '("GtkWindow" "parent")
+    '("GtkWindow*" "parent")
   )
 )
 
diff --git a/bindings/python/totem.override b/bindings/python/totem.override
index 610e3e2..7ad72e4 100644
--- a/bindings/python/totem.override
+++ b/bindings/python/totem.override
@@ -37,21 +37,12 @@ import gtk.Window as PyGtkWindow_Type
 import gtk.gdk.Pixbuf as PyGdkPixbuf_Type
 import gtk.ComboBox as PyGtkComboBox_Type
 import gtk.CellRenderer as PyGtkCellRenderer_Type
+import libpeas.Plugin as PyPeasPlugin_Type
 %%
 ignore-glob
   *_get_type
   *_quark
 %%
-override totem_object_plugins_shutdown noargs
-static PyObject *
-_wrap_totem_object_plugins_shutdown (PyGObject *self)
-{
-	totem_object_plugins_shutdown ();
-
-	Py_INCREF (Py_None);
-	return Py_None;
-}
-%%
 override totem_action_error kwargs
 static PyObject *
 _wrap_totem_action_error (PyGObject *self, PyObject *args, PyObject *kwargs)
@@ -79,7 +70,7 @@ _wrap_totem_interface_error_with_link (PyGObject *self, PyObject *args, PyObject
 	if (!PyArg_ParseTupleAndKeywords (args, kwargs, "ssssO!:TotemObject.interface_error_with_link", kwlist, &title, &reason, &uri, &label, &PyGtkWindow_Type, &parent))
 		return NULL;
     
-	totem_interface_error_with_link (title, reason, uri, label, GTK_WINDOW(parent->obj), TOTEM_OBJECT(self->obj));
+	totem_interface_error_with_link (title, reason, uri, label, GTK_WINDOW(parent->obj));
     
 	Py_INCREF (Py_None);
 	return Py_None;
@@ -89,26 +80,26 @@ override totem_plugin_load_interface kwargs
 static PyObject *
 _wrap_totem_plugin_load_interface (PyGObject *self, PyObject *args, PyObject *kwargs)
 {
-	static char *kwlist[] = { "name", "fatal", "parent", "user_data", NULL };
-	char *name;
-	gboolean fatal;
-	GtkWindow *parent;
-	gpointer user_data;
-	GtkBuilder *builder;
-	PyObject *py_parent;
+       static char *kwlist[] = { "name", "fatal", "parent", "user_data", NULL };
+       char *name;
+       gboolean fatal;
+       GtkWindow *parent;
+       gpointer user_data;
+       GtkBuilder *builder;
+       PyObject *py_parent;
 
-	if (!PyArg_ParseTupleAndKeywords (args, kwargs,"sbOO:TotemPlugin.load_interface", kwlist, &name, &fatal, &py_parent, &user_data))
-		return NULL;
-	if (pygobject_check (py_parent, &PyGtkWindow_Type)) {
-		parent = GTK_WINDOW (pygobject_get (py_parent));
-	} else {
-		PyErr_SetString (PyExc_TypeError, "parent should be a GtkWindow");
-		return NULL;
-	}
+       if (!PyArg_ParseTupleAndKeywords (args, kwargs,"sbOO:TotemPlugin.load_interface", kwlist, &name, &fatal, &py_parent, &user_data))
+               return NULL;
+       if (pygobject_check (py_parent, &PyGtkWindow_Type)) {
+               parent = GTK_WINDOW (pygobject_get (py_parent));
+       } else {
+               PyErr_SetString (PyExc_TypeError, "parent should be a GtkWindow");
+               return NULL;
+       }
     
-	builder = totem_plugin_load_interface (TOTEM_PLUGIN (self->obj), name, fatal, parent, user_data);
+       builder = totem_plugin_load_interface (TOTEM_PLUGIN (self->obj), name, fatal, parent, user_data);
     
-	return pygobject_new ((GObject *)builder);
+       return pygobject_new ((GObject *)builder);
 }
 %%
 override totem_get_version noargs
diff --git a/bindings/python/totemmodule.c b/bindings/python/totemmodule.c
new file mode 100644
index 0000000..6d6c91f
--- /dev/null
+++ b/bindings/python/totemmodule.c
@@ -0,0 +1,230 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * heavily based on code from Rhythmbox and Gedit
+ *
+ * Copyright (C) 2002-2005 Paolo Maggi
+ * Copyright (C) 2007 Bastien Nocera <hadess hadess net>
+ *
+ * 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 St, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Sunday 13th May 2007: Bastien Nocera: Add exception clause.
+ * See license_change file for details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Python.h>
+#include <pygobject.h>
+#include <pygtk/pygtk.h>
+
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif /* PY_VERSION_HEX */
+
+/* Exported by Totem Python module */
+void pytotem_register_classes (PyObject *d);
+void pytotem_add_constants (PyObject *module, const gchar *strip_prefix);
+extern PyMethodDef pytotem_functions[];
+
+/* We retrieve this to check for correct class hierarchy */
+static PyTypeObject *PyTotemPlugin_Type;
+
+DL_EXPORT (void)
+init_totem (void)
+{
+	PyObject *pygtk, *mdict, *require;
+	PyObject *totem, *gtk, *pygtk_version, *pygtk_required_version;
+	PyObject *gettext, *install, *gettext_args;
+//	PyObject *sys_path;
+	struct sigaction old_sigint;
+	gint res;
+	char *argv[] = { "totem", NULL };
+//	char **paths;
+//	guint i;
+
+	g_message ("inittotem is called");
+#if 0
+	if (Py_IsInitialized ()) {
+		g_warning ("Python should only be initialized once, since it's in class_init");
+		g_return_if_reached ();
+	}
+
+	/* Hack to make python not overwrite SIGINT: this is needed to avoid
+	 * the crash reported on gedit bug #326191 */
+
+	/* Save old handler */
+	res = sigaction (SIGINT, NULL, &old_sigint);
+	if (res != 0) {
+		g_warning ("Error initializing Python interpreter: cannot get "
+		           "handler to SIGINT signal (%s)",
+		           strerror (errno));
+
+		return;
+	}
+
+	/* Python initialization */
+	Py_Initialize ();
+
+	/* Restore old handler */
+	res = sigaction (SIGINT, &old_sigint, NULL);
+	if (res != 0) {
+		g_warning ("Error initializing Python interpreter: cannot restore "
+		           "handler to SIGINT signal (%s)",
+		           strerror (errno));
+		return;
+	}
+
+	PySys_SetArgv (1, argv);
+#endif
+	/* pygtk.require("2.8") */
+	pygtk = PyImport_ImportModule ("pygtk");
+	if (pygtk == NULL) {
+		g_warning ("Could not import pygtk");
+		PyErr_Print();
+		return;
+	}
+
+	mdict = PyModule_GetDict (pygtk);
+	require = PyDict_GetItemString (mdict, "require");
+	PyObject_CallObject (require, Py_BuildValue ("(S)", PyString_FromString ("2.8")));
+
+	/* import gobject */
+	init_pygobject ();
+
+	/* disable pyg* log hooks, since ours is more interesting */
+#ifdef pyg_disable_warning_redirections
+	pyg_disable_warning_redirections ();
+#endif
+
+	/* import gtk */
+	init_pygtk ();
+
+	pyg_enable_threads ();
+
+	gtk = PyImport_ImportModule ("gtk");
+	if (gtk == NULL) {
+		g_warning ("Could not import gtk");
+		PyErr_Print();
+		return;
+	}
+
+	mdict = PyModule_GetDict (gtk);
+	pygtk_version = PyDict_GetItemString (mdict, "pygtk_version");
+	pygtk_required_version = Py_BuildValue ("(iii)", 2, 12, 0);
+	if (PyObject_Compare (pygtk_version, pygtk_required_version) == -1) {
+		g_warning("PyGTK %s required, but %s found.",
+				  PyString_AsString (PyObject_Repr (pygtk_required_version)),
+				  PyString_AsString (PyObject_Repr (pygtk_version)));
+		Py_DECREF (pygtk_required_version);
+		return;
+	}
+	Py_DECREF (pygtk_required_version);
+
+#if 0
+	/* import totem */
+	paths = totem_get_plugin_paths ();
+	sys_path = PySys_GetObject ("path");
+	for (i = 0; paths[i] != NULL; i++) {
+		PyObject *path;
+
+		path = PyString_FromString (paths[i]);
+		if (PySequence_Contains (sys_path, path) == 0) {
+			PyList_Insert (sys_path, 0, path);
+		}
+		Py_DECREF (path);
+	}
+	g_strfreev (paths);
+#endif
+	PyObject *mdict2, *tuple;
+
+	/* import gedit */
+	totem = Py_InitModule ("totem._totem", pytotem_functions);
+	mdict = PyModule_GetDict (totem);
+	pytotem_register_classes (mdict);
+	pytotem_add_constants (totem, "TOTEM_");
+
+	/* Set version */
+#if 0
+	tuple = Py_BuildValue ("(iii)",
+			       GEDIT_MAJOR_VERSION,
+			       GEDIT_MINOR_VERSION,
+			       GEDIT_MICRO_VERSION);
+	PyDict_SetItemString (mdict, "version", tuple);
+	Py_DECREF (tuple);
+#endif
+#if 0
+	totem = PyImport_ImportModule ("totem");
+
+	if (totem == NULL) {
+		g_warning ("Could not import Python module 'totem'");
+		PyErr_Print ();
+		return;
+	}
+
+	/* add pytotem_functions */
+	for (res = 0; pytotem_functions[res].ml_name != NULL; res++) {
+		PyObject *func;
+
+		func = PyCFunction_New (&pytotem_functions[res], totem);
+		if (func == NULL) {
+			g_warning ("unable object for function '%s' create", pytotem_functions[res].ml_name);
+			PyErr_Print ();
+			return;
+		}
+		if (PyModule_AddObject (totem, pytotem_functions[res].ml_name, func) < 0) {
+			g_warning ("unable to insert function '%s' in 'totem' module", pytotem_functions[res].ml_name);
+			PyErr_Print ();
+			return;
+		}
+	}
+	mdict = PyModule_GetDict (totem);
+
+	pytotem_register_classes (mdict);
+	pytotem_add_constants (totem, "TOTEM_");
+#endif
+	/* Retrieve the Python type for totem.Plugin */
+	PyTotemPlugin_Type = (PyTypeObject *) PyDict_GetItemString (mdict, "Plugin");
+	if (PyTotemPlugin_Type == NULL) {
+		PyErr_Print ();
+		return;
+	}
+
+	/* i18n support */
+	gettext = PyImport_ImportModule ("gettext");
+	if (gettext == NULL) {
+		g_warning ("Could not import gettext");
+		PyErr_Print();
+		return;
+	}
+
+	mdict = PyModule_GetDict (gettext);
+	install = PyDict_GetItemString (mdict, "install");
+	gettext_args = Py_BuildValue ("ss", GETTEXT_PACKAGE, GNOMELOCALEDIR);
+	PyObject_CallObject (install, gettext_args);
+	Py_DECREF (gettext_args);
+
+	/* ideally totem should clean up the python stuff again at some point,
+	 * for which we'd need to save the result of SaveThread so we can then
+	 * restore the state in a class_finalize or so, but since totem doesn't
+	 * do any clean-up at this point, we'll just skip this as well */
+//	PyEval_SaveThread();
+}
+
diff --git a/bindings/vala/totem.vapi b/bindings/vala/totem.vapi
index d67f393..e8ed670 100644
--- a/bindings/vala/totem.vapi
+++ b/bindings/vala/totem.vapi
@@ -102,7 +102,7 @@ namespace Totem {
 	}
 
 	[CCode (cheader_filename = "totem-plugin.h")]
-	public abstract class Plugin : GLib.Object {
+	public abstract class Plugin :Peas.Plugin {
 		[CCode (has_construct_function = false)]
 		protected Plugin ();
 
diff --git a/configure.in b/configure.in
index 3dd9f9b..b9551b2 100644
--- a/configure.in
+++ b/configure.in
@@ -258,6 +258,13 @@ fi
 AM_CONDITIONAL(HAVE_XVIDMODE, [test x$have_xvidmode = xyes])
 
 dnl ================================================================
+dnl Plugins support
+dnl ================================================================
+
+PKG_CHECK_MODULES(PEAS, libpeas-1.0)
+PKG_CHECK_MODULES(PEASUI, libpeasui-1.0)
+
+dnl ================================================================
 dnl Python plugins
 dnl ================================================================
 
@@ -346,10 +353,6 @@ if test "x$have_python" != "xno"; then
 	AC_SUBST([PYGTK_CODEGEN])
 	AC_SUBST([PYGTK_H2DEF])
 
-dnl	uncomment when http://bugzilla.gnome.org/show_bug.cgi?id=351072 fixed
-dnl	PKG_CHECK_EXISTS([pygobject-2.0 >= X.XX.X],
-dnl			 AC_DEFINE([PYGOBJECT_CAN_MARSHAL_GVALUE]))
-
 	dnl Check for -fno-strict-aliasing
 	FLAGS="-fno-strict-aliasing"
 	save_CFLAGS="$CFLAGS"
@@ -377,8 +380,8 @@ dnl ================================================================
 AC_MSG_CHECKING([whether Vala plugin support is requested])
 AC_ARG_ENABLE([vala],
 	AS_HELP_STRING([--enable-vala],[Enable Vala plugin support]),
-	[enable_vala=$enableval have_vala=$enableval],
-	[enable_vala=autodetect have_vala=yes])
+	[enable_vala=$enableval],
+	[enable_vala=no])
 AC_MSG_RESULT([$enable_vala])
 if test "x$enable_vala" != "xno"; then
 	AM_PROG_VALAC([$VALA_REQS])
@@ -502,7 +505,8 @@ for plugin in ${used_plugins}; do
 			fi
 		;;
 		publish)
-			PKG_CHECK_MODULES(LIBEPC, libepc-ui-1.0 >= 0.3.0, [HAVE_LIBEPC=yes], [HAVE_LIBEPC=no])
+			# FIXME
+			PKG_CHECK_MODULES(LIBEPC, libepc-ui-1.0 >= 0.3.0, [HAVE_LIBEPC=no], [HAVE_LIBEPC=no])
 			if test "${HAVE_LIBEPC}" != "yes" ; then
 				plugin_error_or_ignore "you need the easy-publish-and-consume library installed for the publish plugin"
 				add_plugin="0"
@@ -821,7 +825,6 @@ src/plugins/skipto/Makefile
 src/plugins/sample-python/Makefile
 src/plugins/sample-vala/Makefile
 src/plugins/thumbnail/Makefile
-src/plugins/totem/Makefile
 src/plugins/tracker/Makefile
 src/plugins/youtube/Makefile
 src/plugins/pythonconsole/Makefile
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 3add362..a947590 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -138,7 +138,8 @@ GTKDOC_CFLAGS = \
 	-I$(top_srcdir)/src		\
 	-I$(top_srcdir)/src/backend	\
 	-I$(top_srcdir)/src/plugins	\
-	$(DEPENDENCY_CFLAGS)
+	$(DEPENDENCY_CFLAGS)		\
+	$(PEAS_CFLAGS)
 GTKDOC_LIBS = \
 	$(top_builddir)/src/libtotem_main.la	\
 	$(DEPENDENCY_LIBS)
diff --git a/src/Makefile.am b/src/Makefile.am
index b9194a8..5b82995 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,10 +1,9 @@
 SUBDIRS = plugins backend
 
 bin_PROGRAMS = totem totem-video-thumbnailer totem-video-indexer totem-audio-preview
+lib_LTLIBRARIES = libtotem_main.la
 libexec_PROGRAMS =
-noinst_LTLIBRARIES =				\
-	libtotem_player.la			\
-	libtotem_main.la
+noinst_LTLIBRARIES = libtotem_player.la
 
 common_defines = \
 	-D_REENTRANT					\
@@ -102,9 +101,11 @@ libtotem_main_la_CFLAGS = \
 	$(DBUS_CFLAGS)			\
 	$(MISSING_PLUGINS_CFLAGS)	\
 	$(UNIQUE_CFLAGS)		\
+	$(PEASUI_CFLAGS)		\
 	$(AM_CFLAGS)
 
-libtotem_main_la_LDFLAGS = \
+libtotem_main_la_LDFLAGS =		\
+	-export_dynamic			\
 	$(AM_LDFLAGS)
 
 libtotem_main_la_LIBADD = \
@@ -112,6 +113,8 @@ libtotem_main_la_LIBADD = \
 	backend/libbaconvideowidget.la	\
 	plugins/libtotemmodule.la	\
 	$(UNIQUE_LIBS)			\
+	$(PEASUI_LIBS)			\
+	$(DEPENDENCY_LIBS)		\
 	$(DBUS_LIBS)			\
 	$(XVIDMODE_LIBS)		\
 	$(XTEST_LIBS)			\
@@ -141,12 +144,6 @@ libtotem_main_la_SOURCES += eggsmclient-osx.c
 endif
 endif
 
-if ENABLE_PYTHON
-libtotem_main_la_LIBADD += \
-	$(PYTHON_LIBS)						\
-	$(top_builddir)/bindings/python/totem-python.la
-endif
-
 # Totem
 
 TOTEMMARSHALFILES = 						\
@@ -174,17 +171,19 @@ totem_SOURCES = totem.c
 totem_CPPFLAGS =			\
 	-I$(top_srcdir)/		\
 	-I$(srcdir)/backend		\
+	-I$(srcdir)/plugins		\
 	$(common_defines)		\
 	-DG_LOG_DOMAIN=\""Totem"\"	\
 	$(AM_CPPFLAGS)
 
 totem_CFLAGS =				\
 	$(UNIQUE_CFLAGS)		\
+	$(PEAS_CFLAGS)			\
 	$(WARN_CFLAGS)			\
 	$(DEPENDENCY_CFLAGS)		\
 	$(AM_CFLAGS)
 
-totem_LDFLAGS = \
+totem_LDFLAGS =				\
 	$(AM_LDFLAGS)
 
 totem_LDADD =						\
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 25abd30..e4feb24 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,9 +1,10 @@
-SUBDIRS = $(PLUGINS)
-DIST_SUBDIRS = $(ALL_PLUGINS) totem
+SUBDIRS = screenshot
+#SUBDIRS = $(PLUGINS)
+#DIST_SUBDIRS = $(ALL_PLUGINS)
 
 noinst_LTLIBRARIES = libtotemmodule.la
 
-common_defines = \
+common_defines =					\
 	-D_REENTRANT					\
 	-DDBUS_API_SUBJECT_TO_CHANGE			\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
@@ -18,21 +19,20 @@ common_defines = \
 modules_flags = -export_dynamic -avoid-version -module
 
 libtotemmodule_la_SOURCES =		\
-	totem-module.c			\
-	totem-module.h			\
-	totem-plugin.c			\
-	totem-plugin.h			\
 	totem-plugins-engine.c		\
 	totem-plugins-engine.h		\
-	totem-plugin-manager.c		\
-	totem-plugin-manager.h
+	totem-dirs.c			\
+	totem-dirs.h
 
 libtotemmodule_la_CPPFLAGS = \
 	$(common_defines)	\
 	$(AM_CPPFLAGS)
 
+libtotemmodule_la_LDFLAGS = $(AM_LDFLAGS) $(modules_flags)
+
 libtotemmodule_la_CFLAGS = \
 	$(DEPENDENCY_CFLAGS)	\
+	$(PEAS_CFLAGS)		\
 	$(WARN_CFLAGS)		\
 	$(DBUS_CFLAGS)		\
 	$(AM_CFLAGS)		\
@@ -43,27 +43,3 @@ libtotemmodule_la_CFLAGS = \
 	-I$(top_srcdir)/src/backend			\
 	-I$(top_srcdir)/src/plugins
 
-libtotemmodule_la_LDFLAGS = \
-	$(AM_LDFLAGS)			
-
-if ENABLE_PYTHON
-
-SUBDIRS += totem
-
-libtotemmodule_la_LIBADD = \
-	$(DEPENDENCY_LIBS)	\
-	$(PYTHON_LIBS)		\
-	$(PYTHON_EXTRA_LIBS)	\
-	$(PYGTK_LIBS)
-
-libtotemmodule_la_SOURCES += \
-	totem-python-module.c		\
-	totem-python-module.h		\
-	totem-python-plugin.c		\
-	totem-python-plugin.h
-
-libtotemmodule_la_CFLAGS += \
-	$(NO_STRICT_ALIASING_CFLAGS)	\
-	$(PYGTK_CFLAGS)			\
-	$(PYTHON_CFLAGS)
-endif
diff --git a/src/plugins/totem-dirs.c b/src/plugins/totem-dirs.c
new file mode 100644
index 0000000..4209096
--- /dev/null
+++ b/src/plugins/totem-dirs.c
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * heavily based on code from Rhythmbox and Gedit
+ *
+ * Copyright (C) 2002-2005 Paolo Maggi
+ * Copyright (C) 2007 Bastien Nocera <hadess hadess net>
+ *
+ * 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 St, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Sunday 13th May 2007: Bastien Nocera: Add exception clause.
+ * See license_change file for details.
+ *
+ */
+
+/**
+ * SECTION:totem-plugin
+ * @short_description: base plugin class and loading/unloading functions
+ * @stability: Unstable
+ * @include: totem-plugin.h
+ *
+ * #TotemPlugin is a general-purpose architecture for adding plugins to Totem, with
+ * derived support for different programming languages.
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gconf/gconf-client.h>
+
+#include "totem-dirs.h"
+#include "totem-plugins-engine.h"
+#include "totem-uri.h"
+#include "totem-interface.h"
+
+#define UNINSTALLED_PLUGINS_LOCATION "plugins"
+
+char **
+totem_get_plugin_paths (void)
+{
+	GPtrArray *paths;
+	char  *path;
+	GConfClient *client;
+	gboolean uninstalled;
+
+	paths = g_ptr_array_new ();
+	uninstalled = FALSE;
+
+#ifdef TOTEM_RUN_IN_SOURCE_TREE
+	path = g_build_filename (UNINSTALLED_PLUGINS_LOCATION, NULL);
+	if (g_file_test (path, G_FILE_TEST_IS_DIR) != FALSE) {
+		uninstalled = TRUE;
+		g_ptr_array_add (paths, path);
+	}
+#endif
+
+	client = gconf_client_get_default ();
+	if (gconf_client_get_bool (client, GCONF_PREFIX"/disable_user_plugins", NULL) == FALSE) {
+		path = g_build_filename (totem_data_dot_dir (), "plugins", NULL);
+		g_ptr_array_add (paths, path);
+	}
+
+	if (uninstalled == FALSE) {
+		path = g_strdup (TOTEM_PLUGIN_DIR);
+		g_ptr_array_add (paths, path);
+	}
+
+	/* And null-terminate the array */
+	g_ptr_array_add (paths, NULL);
+
+	return (char **) g_ptr_array_free (paths, FALSE);
+}
+
+/**
+ * totem_plugin_find_file:
+ * @plugin_name: the plugin name
+ * @file: the file to find
+ *
+ * Finds the specified @file by looking in the plugin paths
+ * listed by totem_get_plugin_paths() and then in the system
+ * Totem data directory.
+ *
+ * This should be used by plugins to find plugin-specific
+ * resource files.
+ *
+ * Return value: a newly-allocated absolute path for the file, or %NULL
+ **/
+char *
+totem_plugin_find_file (const char *plugin_name,
+			const char *file)
+{
+	TotemPluginsEngine *engine;
+	PeasPluginInfo *info;
+	const char *dir;
+	char *tmp;
+	char *ret = NULL;
+
+	engine = totem_plugins_engine_get_default (NULL);
+	info = peas_engine_get_plugin_info (PEAS_ENGINE (engine), plugin_name);
+
+	dir = peas_plugin_info_get_module_dir (info);
+	tmp = g_build_filename (dir, file, NULL);
+	if (g_file_test (tmp, G_FILE_TEST_EXISTS))
+		ret = tmp;
+	else
+		g_free (tmp);
+
+	if (ret == NULL) {
+		dir = peas_plugin_info_get_data_dir (info);
+		tmp = g_build_filename (dir, file, NULL);
+		if (g_file_test (tmp, G_FILE_TEST_EXISTS))
+			ret = tmp;
+		else
+			g_free (tmp);
+	}
+
+	/* global data files */
+	if (ret == NULL)
+		ret = totem_interface_get_full_path (file);
+
+	//FIXME
+#if 0
+	/* ensure it's an absolute path, so doesn't confuse rb_glade_new et al */
+	if (ret && ret[0] != '/') {
+		char *pwd = g_get_current_dir ();
+		char *path = g_strconcat (pwd, G_DIR_SEPARATOR_S, ret, NULL);
+		g_free (ret);
+		g_free (pwd);
+		ret = path;
+	}
+#endif
+	return ret;
+}
+
+/**
+ * totem_plugin_load_interface:
+ * @plugin_name: the plugin name
+ * @name: interface filename
+ * @fatal: %TRUE if it's a fatal error if the interface can't be loaded
+ * @parent: the interface's parent #GtkWindow
+ * @user_data: a pointer to be passed to each signal handler in the interface when they're called
+ *
+ * Loads an interface file (GtkBuilder UI file) for a plugin, given its filename and
+ * assuming it's installed in the plugin's data directory.
+ *
+ * This should be used instead of attempting to load interfaces manually in plugins.
+ *
+ * Return value: the #GtkBuilder instance for the interface
+ **/
+GtkBuilder *
+totem_plugin_load_interface (const char *plugin_name,
+			     const char *name,
+			     gboolean fatal,
+			     GtkWindow *parent,
+			     gpointer user_data)
+{
+	GtkBuilder *builder = NULL;
+	char *filename;
+
+	filename = totem_plugin_find_file (plugin_name, name);
+	builder = totem_interface_load_with_full_path (filename,
+						       fatal,
+						       parent,
+						       user_data);
+	g_free (filename);
+
+	return builder;
+}
diff --git a/src/plugins/totem-python-plugin.h b/src/plugins/totem-dirs.h
similarity index 58%
rename from src/plugins/totem-python-plugin.h
rename to src/plugins/totem-dirs.h
index 442e3e9..57ce860 100644
--- a/src/plugins/totem-python-plugin.h
+++ b/src/plugins/totem-dirs.h
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Heavily based on code from Rhythmbox and Gedit.
+ * heavily based on code from Rhythmbox and Gedit
  *
- * Copyright (C) 2005 Raphael Slinckx
- * Copyright (C) 2007 Philip Withnall
+ * Copyright (C) 2002-2005 Paolo Maggi
+ * Copyright (C) 2007 Bastien Nocera <hadess hadess net>
  *
  * 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
@@ -20,33 +20,20 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA 02110-1301  USA.
  *
- * Saturday 19th May 2007: Philip Withnall: Add exception clause.
+ * Sunday 13th May 2007: Bastien Nocera: Add exception clause.
  * See license_change file for details.
+ *
  */
 
-#ifndef TOTEM_PYTHON_OBJECT_H
-#define TOTEM_PYTHON_OBJECT_H
-
-#include <Python.h>
-#include <glib-object.h>
-#include "totem-plugin.h"
-
-G_BEGIN_DECLS
-
-typedef struct
-{
-	TotemPlugin parent_slot;
-	PyObject *instance;
-} TotemPythonObject;
-
-typedef struct
-{
-	TotemPluginClass parent_slot;
-	PyObject *type;
-} TotemPythonObjectClass;
-
-GType totem_python_object_get_type (GTypeModule *module, PyObject *type);
+#include <glib.h>
+#include <gtk/gtk.h>
 
-G_END_DECLS
+char ** totem_get_plugin_paths (void);
+char * totem_plugin_find_file (const char *plugin_name,
+			       const char *file);
+GtkBuilder * totem_plugin_load_interface (const char *plugin_name,
+					  const char *name,
+					  gboolean fatal,
+					  GtkWindow *parent,
+					  gpointer user_data);
 
-#endif
diff --git a/src/plugins/totem-plugins-engine.c b/src/plugins/totem-plugins-engine.c
index 16e3c33..7972838 100644
--- a/src/plugins/totem-plugins-engine.c
+++ b/src/plugins/totem-plugins-engine.c
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Plugin engine for Totem, heavily based on the code from Rhythmbox,
- * which is based heavily on the code from gedit.
+ * which is based heavily on the code from totem.
  *
  * Copyright (C) 2002-2005 Paolo Maggi
  *               2006 James Livingston  <jrl ids org au>
@@ -36,744 +36,275 @@
 #include <glib/gi18n.h>
 #include <glib.h>
 #include <gconf/gconf-client.h>
+#include <girepository.h>
+#include <libpeas/peas-activatable.h>
+#include <libpeas/peas-extension-set.h>
 
-#include "totem-plugin.h"
-
-#include "totem-module.h"
-#include "totem-interface.h"
-
-#ifdef ENABLE_PYTHON
-#include "totem-python-module.h"
-#endif
-
+#include "totem-dirs.h"
 #include "totem-plugins-engine.h"
 
-#define PLUGIN_EXT	".totem-plugin"
 #define GCONF_PREFIX_PLUGINS GCONF_PREFIX"/plugins"
 #define GCONF_PREFIX_PLUGIN GCONF_PREFIX"/plugins/%s"
 #define GCONF_PLUGIN_ACTIVE GCONF_PREFIX_PLUGINS"/%s/active"
 #define GCONF_PLUGIN_HIDDEN GCONF_PREFIX_PLUGINS"/%s/hidden"
 
-typedef enum
-{
-	TOTEM_PLUGIN_LOADER_C,
-	TOTEM_PLUGIN_LOADER_PY
-} TotemPluginLang;
-
-struct _TotemPluginInfo
-{
-	gchar        *file;
-
-	gchar        *location;
-	TotemPluginLang lang;
-	GTypeModule  *module;
-
-	gchar        *name;
-	gchar        *desc;
-	gchar        **authors;
-	gchar        *copyright;
-	gchar        *website;
-
-	gchar        *icon_name;
-	GdkPixbuf    *icon_pixbuf;
-
-	TotemPlugin     *plugin;
-
-	gboolean     builtin;
-	gboolean     active;
-	gboolean     visible;
-	guint        active_notification_id;
-	guint        visible_notification_id;
-};
-
-static void totem_plugin_info_free (TotemPluginInfo *info);
-static void totem_plugins_engine_plugin_active_cb (GConfClient *client,
-						guint cnxn_id,
-						GConfEntry *entry,
-						TotemPluginInfo *info);
-static void totem_plugins_engine_plugin_visible_cb (GConfClient *client,
-						 guint cnxn_id,
-						 GConfEntry *entry,
-						 TotemPluginInfo *info);
-static gboolean totem_plugins_engine_activate_plugin_real (TotemPluginInfo *info,
-							TotemObject *totem,
-							GError **error);
-static void totem_plugins_engine_deactivate_plugin_real (TotemPluginInfo *info,
-						      TotemObject *totem);
-
-static GHashTable *totem_plugins = NULL;
-guint garbage_collect_id = 0;
-TotemObject *totem_plugins_object = NULL;
-static GConfClient *client = NULL;
-
-static TotemPluginInfo *
-totem_plugins_engine_load (const gchar *file)
-{
-	TotemPluginInfo *info;
-	GKeyFile *plugin_file = NULL;
-	GError *err = NULL;
-	gchar *str;
-
-	g_return_val_if_fail (file != NULL, NULL);
-
-	info = g_new0 (TotemPluginInfo, 1);
-	info->file = g_strdup (file);
-
-	plugin_file = g_key_file_new ();
-	if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL)) {
-		g_warning ("Bad plugin file: %s", file);
-		goto error;
-	}
-
-	if (!g_key_file_has_key (plugin_file,
-			   	 "Totem Plugin",
-				 "IAge",
-				 NULL))	{
-		goto error;
-	}
-
-	/* Check IAge=1 */
-	if (g_key_file_get_integer (plugin_file,
-				    "Totem Plugin",
-				    "IAge",
-				    NULL) != 1)	{
-		goto error;
-	}
-
-	/* Get Location */
-	str = g_key_file_get_string (plugin_file,
-				     "Totem Plugin",
-				     "Module",
-				     NULL);
-	if (str) {
-		info->location = str;
-	} else {
-		g_warning ("Could not find 'Module' in %s", file);
-		goto error;
-	}
-
-	/* Get the loader for this plugin */
-	str = g_key_file_get_string (plugin_file,
-				     "Totem Plugin",
-				     "Loader",
-				     NULL);
-	if (str && strcmp(str, "python") == 0) {
-		info->lang = TOTEM_PLUGIN_LOADER_PY;
-#ifndef ENABLE_PYTHON
-		g_warning ("Cannot load Python extension '%s', Totem was not compiled with Python support", file);
-		g_free (str);
-		goto error;
-#endif
-	} else {
-		info->lang = TOTEM_PLUGIN_LOADER_C;
-	}
-	g_free (str);
-
-	/* Get Name */
-	str = g_key_file_get_locale_string (plugin_file,
-					    "Totem Plugin",
-					    "Name",
-					    NULL, NULL);
-	if (str) {
-		info->name = str;
-	} else {
-		g_warning ("Could not find 'Name' in %s", file);
-		goto error;
-	}
-
-	/* Get Description */
-	str = g_key_file_get_locale_string (plugin_file,
-					    "Totem Plugin",
-					    "Description",
-					    NULL, NULL);
-	if (str) {
-		info->desc = str;
-	} else {
-		info->desc = g_strdup ("");
-	}
-
-	/* Get icon name */
-	str = g_key_file_get_string (plugin_file,
-				     "Totem Plugin",
-				     "Icon",
-				     NULL);
-	if (str) {
-		info->icon_name = str;
-	} else {
-		info->icon_name = g_strdup ("");
-	}
-
-	/* Get Authors */
-	info->authors = g_key_file_get_string_list (plugin_file,
-						    "Totem Plugin",
-						    "Authors",
-						    NULL, NULL);
-
-	/* Get Copyright */
-	str = g_key_file_get_string (plugin_file,
-				     "Totem Plugin",
-				     "Copyright",
-				     NULL);
-	if (str) {
-		info->copyright = str;
-	} else {
-		info->copyright = g_strdup ("");
-	}
-
-	/* Get Copyright */
-	str = g_key_file_get_string (plugin_file,
-				     "Totem Plugin",
-				     "Website",
-				     NULL);
-	if (str) {
-		info->website = str;
-	} else {
-		info->website = g_strdup ("");
-	
-	}
-
-	/* Get Builtin */
-	info->builtin = g_key_file_get_boolean (plugin_file,
-						"Totem Plugin",
-						"Builtin",
-						&err);
-	if (err != NULL) {
-		info->builtin = FALSE;
-		g_error_free (err);
-	}
-
-	g_key_file_free (plugin_file);
-
-	return info;
-
-error:
-	g_warning ("Failed to load plugin file: %s", file);
-	g_free (info->file);
-	g_free (info->location);
-	g_free (info->name);
-	g_free (info);
-	g_key_file_free (plugin_file);
-
-	return NULL;
-}
-
-static void
-totem_plugins_engine_load_file (const char *plugin_file)
-{
-	TotemPluginInfo *info;
-	char *key_name;
-	GConfValue *activate_value;
-	gboolean activate;
-
-	if (g_str_has_suffix (plugin_file, PLUGIN_EXT) == FALSE)
-		return;
-
-	info = totem_plugins_engine_load (plugin_file);
-	if (info == NULL)
-		return;
-
-	if (g_hash_table_lookup (totem_plugins, info->location)) {
-		totem_plugin_info_free (info);
-		return;
-	}
-
-	g_hash_table_insert (totem_plugins, info->location, info);
-
-	key_name = g_strdup_printf (GCONF_PREFIX_PLUGIN, info->location);
-	gconf_client_add_dir (client, key_name, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
-	g_free (key_name);
-
-	key_name = g_strdup_printf (GCONF_PLUGIN_ACTIVE, info->location);
-	info->active_notification_id = gconf_client_notify_add (client,
-								key_name,
-								(GConfClientNotifyFunc)totem_plugins_engine_plugin_active_cb,
-								info,
-								NULL,
-								NULL);
-	activate_value = gconf_client_get (client, key_name, NULL);
-	g_free (key_name);
-
-	if (activate_value == NULL) {
-		/* Builtin plugins are activated by default; other plugins aren't */
-		activate = info->builtin;
-	} else {
-		activate = gconf_value_get_bool (activate_value);
-		gconf_value_free (activate_value);
-	}
-
-	if (info->builtin == FALSE) {
-		/* Builtin plugins are *always* invisible */
-		key_name = g_strdup_printf (GCONF_PLUGIN_HIDDEN, info->location);
-		info->visible_notification_id = gconf_client_notify_add (client,
-									 key_name,
-									 (GConfClientNotifyFunc)totem_plugins_engine_plugin_visible_cb,
-									 info,
-									 NULL,
-									 NULL);
-		info->visible = !gconf_client_get_bool (client, key_name, NULL);
-		g_free (key_name);
-	}
-
-	if (activate)
-		totem_plugins_engine_activate_plugin (info);
-}
-
-static void
-totem_plugins_engine_load_dir (const gchar *path)
-{
-	GDir *dir;
-	const char *name;
-
-	dir = g_dir_open (path, 0, NULL);
-	if (dir == NULL)
-		return;
-
-	while ((name = g_dir_read_name (dir)) != NULL) {
-		char *filename;
-
-		filename = g_build_filename (path, name, NULL);
-		if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE) {
-			totem_plugins_engine_load_dir (filename);
-		} else {
-			totem_plugins_engine_load_file (filename);
-		}
-		g_free (filename);
-	}
-	g_dir_close (dir);
-}
-
-static void
-totem_plugins_engine_load_all (void)
-{
-	GList *paths;
-
-	paths = totem_get_plugin_paths ();
-	while (paths != NULL) {
-		totem_plugins_engine_load_dir (paths->data);
-		g_free (paths->data);
-		paths = g_list_delete_link (paths, paths);
-	}
-}
-
+typedef struct _TotemPluginsEnginePrivate{
+	PeasExtensionSet *activatable_extensions;
+	TotemObject *totem;
+	GConfClient *client;
+	guint notification_id;
+	guint garbage_collect_id;
+} _TotemPluginsEnginePrivate;
+
+G_DEFINE_TYPE(TotemPluginsEngine, totem_plugins_engine, PEAS_TYPE_ENGINE)
+
+static void totem_plugins_engine_finalize (GObject *object);
+static void totem_plugins_engine_gconf_cb (GConfClient *gconf_client,
+					   guint cnxn_id,
+					   GConfEntry *entry,
+					   TotemPluginsEngine *engine);
 #if 0
-#ifdef ENABLE_PYTHON
+static void totem_plugins_engine_activate_plugin (PeasEngine     *engine,
+						  PeasPluginInfo *info);
+static void totem_plugins_engine_deactivate_plugin (PeasEngine     *engine,
+						    PeasPluginInfo *info);
+#endif
 static gboolean
 garbage_collect_cb (gpointer data)
 {
-	/* Commented out due to line 387 being commented out. More's commented out in totem-python-module.c. */
-	totem_plugins_engine_garbage_collect ();
+	TotemPluginsEngine *engine = (TotemPluginsEngine *) data;
+	peas_engine_garbage_collect (PEAS_ENGINE (engine));
 	return TRUE;
 }
-#endif
-#endif
-
-gboolean
-totem_plugins_engine_init (TotemObject *totem)
-{
-	g_return_val_if_fail (totem_plugins == NULL, FALSE);
-
-	if (!g_module_supported ())
-	{
-		g_warning ("Totem is not able to initialize the plugins engine.");
-		return FALSE;
-	}
-	totem_plugins = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)totem_plugin_info_free);
-
-	totem_plugins_object = totem;
-	g_object_ref (G_OBJECT (totem_plugins_object));
-
-	client = gconf_client_get_default ();
-
-	totem_plugins_engine_load_all ();
-
-#if 0
-#ifdef ENABLE_PYTHON
-	/* Commented out because it's a no-op. A further section is commented out below, and more's commented out
-	 * in totem-python-module.c. */
-	garbage_collect_id = g_timeout_add_seconds_full (G_PRIORITY_LOW, 20, garbage_collect_cb, NULL, NULL);
-#endif
-#endif
-
-	return TRUE;
-}
-
-void
-totem_plugins_engine_garbage_collect (void)
-{
-#ifdef ENABLE_PYTHON
-	totem_python_garbage_collect ();
-#endif
-}
 
 static void
-totem_plugin_info_free (TotemPluginInfo *info)
+totem_plugins_engine_class_init (TotemPluginsEngineClass *klass)
 {
-	if (info->active)
-		totem_plugins_engine_deactivate_plugin_real (info, totem_plugins_object);
-
-	if (info->plugin != NULL) {
-		g_object_unref (info->plugin);
-
-		/* info->module must not be unref since it is not possible to finalize
-		 * a type module */
-	}
-
-	if (info->active_notification_id > 0)
-		gconf_client_notify_remove (client, info->active_notification_id);
-	if (info->visible_notification_id > 0)
-		gconf_client_notify_remove (client, info->visible_notification_id);
-
-	g_free (info->file);
-	g_free (info->location);
-	g_free (info->name);
-	g_free (info->desc);
-	g_free (info->website);
-	g_free (info->copyright);
-	g_free (info->icon_name);
-
-	if (info->icon_pixbuf)
-		g_object_unref (info->icon_pixbuf);
-	g_strfreev (info->authors);
-
-	g_free (info);
-}
-
-void
-totem_plugins_engine_shutdown (void)
-{
-	if (totem_plugins != NULL)
-		g_hash_table_destroy (totem_plugins);
-	totem_plugins = NULL;
-
-	if (totem_plugins_object != NULL)
-		g_object_unref (totem_plugins_object);
-	totem_plugins_object = NULL;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-#if 0
-#ifdef ENABLE_PYTHON
-	if (garbage_collect_id > 0)
-		g_source_remove (garbage_collect_id);
-	totem_plugins_engine_garbage_collect ();
-#endif
-#endif
-
-	if (client != NULL)
-		g_object_unref (client);
-	client = NULL;
-
-#ifdef ENABLE_PYTHON
-	totem_python_shutdown ();
-#endif
-}
-
-static void
-collate_values_cb (gpointer key, gpointer value, GList **list)
-{
-	*list = g_list_prepend (*list, value);
-}
-
-GList *
-totem_plugins_engine_get_plugins_list (void)
-{
-	GList *list = NULL;
-
-	if (totem_plugins == NULL)
-		return NULL;
-
-	g_hash_table_foreach (totem_plugins, (GHFunc)collate_values_cb, &list);
-	list = g_list_reverse (list);
-
-	return list;
+	object_class->finalize = totem_plugins_engine_finalize;
+	g_type_class_add_private (klass, sizeof (TotemPluginsEnginePrivate));
 }
 
 static gboolean
-load_plugin_module (TotemPluginInfo *info)
+plugin_is_builtin (PeasPluginInfo *info)
 {
-	gchar *path;
-	gchar *dirname;
-
-	g_return_val_if_fail (info != NULL, FALSE);
-	g_return_val_if_fail (info->file != NULL, FALSE);
-	g_return_val_if_fail (info->location != NULL, FALSE);
-	g_return_val_if_fail (info->plugin == NULL, FALSE);
-
-	switch (info->lang) {
-		case TOTEM_PLUGIN_LOADER_C:
-			dirname = g_path_get_dirname (info->file);
-			g_return_val_if_fail (dirname != NULL, FALSE);
-
-			path = g_module_build_path (dirname, info->location);
-#ifdef TOTEM_RUN_IN_SOURCE_TREE
-			if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
-				char *temp;
-
-				g_free (path);
-				temp = g_build_filename (dirname, ".libs", NULL);
-
-				path = g_module_build_path (temp, info->location);
-				g_free (temp);
-			}
-#endif
-
-			g_free (dirname);
-			g_return_val_if_fail (path != NULL, FALSE);
-
-			info->module = G_TYPE_MODULE (totem_module_new (path, info->location));
-			g_free (path);
-			break;
-		case TOTEM_PLUGIN_LOADER_PY:
-#ifdef ENABLE_PYTHON
-			info->module = G_TYPE_MODULE (totem_python_module_new (info->file, info->location));
-#else
-			g_warning ("Cannot load plugin %s, Python plugin support is disabled", info->location);
-#endif
-			break;
-		default:
-			g_assert_not_reached ();
-	}
-
-	if (g_type_module_use (info->module) == FALSE) {
-		g_warning ("Could not load plugin %s\n", info->location);
-
-		g_object_unref (G_OBJECT (info->module));
-		info->module = NULL;
+	const GHashTable *keys;
+	const GValue *value;
+	gboolean builtin;
 
+	keys = peas_plugin_info_get_keys (info);
+	if (keys == NULL)
+		return FALSE;
+	value = g_hash_table_lookup ((GHashTable *) keys, "Builtin");
+	if (value == NULL)
 		return FALSE;
-	}
-
-	switch (info->lang) {
-		case TOTEM_PLUGIN_LOADER_C:
-			info->plugin = TOTEM_PLUGIN (totem_module_new_object (TOTEM_MODULE (info->module)));
-			break;
-		case TOTEM_PLUGIN_LOADER_PY:
-#ifdef ENABLE_PYTHON
-			info->plugin = TOTEM_PLUGIN (totem_python_module_new_object (TOTEM_PYTHON_MODULE (info->module)));
-#endif
-			break;
-		default:
-			g_assert_not_reached ();
-	}
-
-	return TRUE;
-}
-
-static gboolean
-totem_plugins_engine_activate_plugin_real (TotemPluginInfo *info, TotemObject *totem, GError **error)
-{
-	gboolean res = TRUE;
-
-	if (info->plugin == NULL)
-		res = load_plugin_module (info);
 
-	if (res)
-		res = totem_plugin_activate (info->plugin, totem, error);
-	else
-		g_warning ("Error, impossible to activate plugin '%s'", info->name);
+	builtin = g_value_get_boolean (value);
+	if (builtin != FALSE)
+		peas_plugin_info_set_visible (info, FALSE);
 
-	return res;
+	return builtin;
 }
 
-gboolean
-totem_plugins_engine_activate_plugin (TotemPluginInfo *info)
+static void
+totem_plugins_engine_load_all (TotemPluginsEngine *engine)
 {
-	char *msg;
-	GError *error = NULL;
-	gboolean ret;
+	const GList *list, *l;
+	GPtrArray *activate;
 
-	g_return_val_if_fail (info != NULL, FALSE);
+	g_message ("totem_plugins_engine_load_all");
 
-	if (info->active)
-		return TRUE;
-
-	ret = totem_plugins_engine_activate_plugin_real (info, totem_plugins_object, &error);
-	if (info->visible != FALSE || ret != FALSE) {
+	activate = g_ptr_array_new ();
+	list = peas_engine_get_plugin_list (PEAS_ENGINE (engine));
+	for (l = list; l != NULL; l = l->next) {
+		PeasPluginInfo *info = l->data;
 		char *key_name;
 
-		key_name = g_strdup_printf (GCONF_PLUGIN_ACTIVE, info->location);
-		gconf_client_set_bool (client, key_name, ret, NULL);
-		g_free (key_name);
-	}
-
-	info->active = ret;
+		g_message ("checking peas_plugin_info_get_module_name (info) %s", peas_plugin_info_get_module_name (info));
 
-	if (ret != FALSE)
-		return TRUE;
+		/* Builtin plugins are activated by default; other plugins aren't */
+		if (plugin_is_builtin (info)) {
+			g_ptr_array_add (activate, (gpointer) peas_plugin_info_get_module_name (info));
+			g_message ("peas_plugin_info_get_module_name (info) %s, to activate", peas_plugin_info_get_module_name (info));
+			continue;
+		}
+		key_name = g_strdup_printf (GCONF_PLUGIN_ACTIVE, peas_plugin_info_get_module_name (info));
+		if (gconf_client_get_bool (engine->priv->client, key_name, NULL) != FALSE) {
+			g_message ("peas_plugin_info_get_module_name (info) %s, to activate", peas_plugin_info_get_module_name (info));
+			g_ptr_array_add (activate, (gpointer) peas_plugin_info_get_module_name (info));
+		}
+		g_free (key_name);
 
-	if (error != NULL) {
-		msg = g_strdup_printf (_("Unable to activate plugin %s.\n%s"), info->name, error->message);
-		g_error_free (error);
-	} else {
-		msg = g_strdup_printf (_("Unable to activate plugin %s"), info->name);
+		key_name = g_strdup_printf (GCONF_PLUGIN_HIDDEN, peas_plugin_info_get_module_name (info));
+		if (gconf_client_get_bool (engine->priv->client, key_name, NULL) != FALSE)
+			peas_plugin_info_set_visible (info, FALSE);
+		g_free (key_name);
 	}
-	totem_interface_error (_("Plugin Error"), msg, NULL);
-	g_free (msg);
+	g_ptr_array_add (activate, NULL);
 
-	return FALSE;
+	peas_engine_set_active_plugins (PEAS_ENGINE (engine), (const char **) activate->pdata);
+	g_ptr_array_free (activate, TRUE);
 }
 
 static void
-totem_plugins_engine_deactivate_plugin_real (TotemPluginInfo *info, TotemObject *totem)
+totem_plugins_engine_monitor (TotemPluginsEngine *engine)
 {
-	totem_plugin_deactivate (info->plugin, totem_plugins_object);
+	engine->priv->notification_id = gconf_client_notify_add (engine->priv->client,
+								GCONF_PREFIX_PLUGINS,
+								(GConfClientNotifyFunc)totem_plugins_engine_gconf_cb,
+								engine,
+								NULL,
+								NULL);
 }
 
-gboolean
-totem_plugins_engine_deactivate_plugin (TotemPluginInfo *info)
+static void
+on_activatable_extension_added (PeasExtensionSet *set,
+				PeasPluginInfo   *info,
+				PeasExtension    *exten,
+				TotemPluginsEngine *engine)
 {
-	char *key_name;
-
-	g_return_val_if_fail (info != NULL, FALSE);
-
-	if (!info->active)
-		return TRUE;
-
-	totem_plugins_engine_deactivate_plugin_real (info, totem_plugins_object);
-
-	/* Update plugin state */
-	info->active = FALSE;
-
-	key_name = g_strdup_printf (GCONF_PLUGIN_ACTIVE, info->location);
-	gconf_client_set_bool (client, key_name, FALSE, NULL);
-	g_free (key_name);
-
-	return TRUE;
+	g_message ("on_activatable_extension_added");
+	peas_extension_call (exten, "activate", engine->priv->totem);
 }
 
-gboolean
-totem_plugins_engine_plugin_is_active (TotemPluginInfo *info)
+static void
+on_activatable_extension_removed (PeasExtensionSet *set,
+				  PeasPluginInfo   *info,
+				  PeasExtension    *exten,
+				  TotemPluginsEngine *engine)
 {
-	g_return_val_if_fail (info != NULL, FALSE);
-
-	return info->active;
+	g_message ("on_activatable_extension_removed");
+	peas_extension_call (exten, "deactivate", engine->priv->totem);
 }
 
-gboolean
-totem_plugins_engine_plugin_is_visible (TotemPluginInfo *info)
+TotemPluginsEngine *
+totem_plugins_engine_get_default (TotemObject *totem)
 {
-	g_return_val_if_fail (info != NULL, FALSE);
+	static TotemPluginsEngine *engine = NULL;
+	char **paths;
+	GPtrArray *array;
+	guint i;
 
-	return info->visible;
-}
+	if (G_LIKELY (engine != NULL))
+		return engine;
 
-gboolean
-totem_plugins_engine_plugin_is_configurable (TotemPluginInfo *info)
-{
-	g_return_val_if_fail (info != NULL, FALSE);
+	g_return_val_if_fail (totem != NULL, NULL);
 
-	if ((info->plugin == NULL) || !info->active)
-		return FALSE;
+	g_irepository_require (g_irepository_get_default (), "Peas", "1.0", 0, NULL);
 
-	return totem_plugin_is_configurable (info->plugin);
-}
+	paths = totem_get_plugin_paths ();
 
-void
-totem_plugins_engine_configure_plugin (TotemPluginInfo *info,
-				       GtkWindow       *parent)
-{
-	GtkWidget *conf_dlg;
+	/* Totem uses the libdir even for noarch data */
+	array = g_ptr_array_new ();
+	for (i = 0; paths[i] != NULL; i++) {
+		g_ptr_array_add (array, paths[i]);
+		g_ptr_array_add (array, paths[i]);
+	}
+	g_ptr_array_add (array, NULL);
 
-	GtkWindowGroup *wg;
+	engine = TOTEM_PLUGINS_ENGINE (g_object_new (TOTEM_TYPE_PLUGINS_ENGINE,
+						     "app-name", "Totem",
+						     "search-paths", array->pdata,
+						     "base-module-dir", TOTEM_PLUGIN_DIR,
+						     NULL));
+	g_strfreev (paths);
+	g_ptr_array_free (array, TRUE);
 
-	g_return_if_fail (info != NULL);
+	g_object_add_weak_pointer (G_OBJECT (engine),
+				   (gpointer) &engine);
 
-	conf_dlg = totem_plugin_create_configure_dialog (info->plugin);
-	g_return_if_fail (conf_dlg != NULL);
-	gtk_window_set_transient_for (GTK_WINDOW (conf_dlg),
-				      parent);
+	engine->priv->totem = g_object_ref (totem);
 
-	wg = gtk_window_get_group (parent);
-	if (wg == NULL)
-	{
-		wg = gtk_window_group_new ();
-		gtk_window_group_add_window (wg, parent);
-	}
+	engine->priv->activatable_extensions = peas_extension_set_new (PEAS_ENGINE (engine),
+								       PEAS_TYPE_ACTIVATABLE);
+	totem_plugins_engine_load_all (engine);
+	totem_plugins_engine_monitor (engine);
 
-	gtk_window_group_add_window (wg,
-				     GTK_WINDOW (conf_dlg));
+	peas_extension_set_call (engine->priv->activatable_extensions, "activate", engine->priv->totem);
 
-	gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE);
-	gtk_widget_show (conf_dlg);
-}
+	g_signal_connect (engine->priv->activatable_extensions, "extension-added",
+			  G_CALLBACK (on_activatable_extension_added), engine);
+	g_signal_connect (engine->priv->activatable_extensions, "extension-removed",
+			  G_CALLBACK (on_activatable_extension_removed), engine);
 
-static void
-totem_plugins_engine_plugin_active_cb (GConfClient *gconf_client,
-				       guint cnxn_id,
-				       GConfEntry *entry,
-				       TotemPluginInfo *info)
-{
-	if (gconf_value_get_bool (entry->value)) {
-		totem_plugins_engine_activate_plugin (info);
-	} else {
-		totem_plugins_engine_deactivate_plugin (info);
-	}
+	return engine;
 }
 
 static void
-totem_plugins_engine_plugin_visible_cb (GConfClient *gconf_client,
-					guint cnxn_id,
-					GConfEntry *entry,
-					TotemPluginInfo *info)
-{
-	info->visible = !gconf_value_get_bool (entry->value);
-}
-
-const gchar *
-totem_plugins_engine_get_plugin_name (TotemPluginInfo *info)
+totem_plugins_engine_init (TotemPluginsEngine *engine)
 {
-	g_return_val_if_fail (info != NULL, NULL);
+	engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine,
+						    TOTEM_TYPE_PLUGINS_ENGINE,
+						    TotemPluginsEnginePrivate);
+	engine->priv->client = gconf_client_get_default ();
+	gconf_client_add_dir (engine->priv->client, GCONF_PREFIX_PLUGINS, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
 
-	return info->name;
+	/* Commented out because it's a no-op. A further section is commented out below, and more's commented out
+	 * in totem-python-module.c. */
+	engine->priv->garbage_collect_id = g_timeout_add_seconds_full (G_PRIORITY_LOW, 20, garbage_collect_cb, engine, NULL);
 }
 
-const gchar *
-totem_plugins_engine_get_plugin_description (TotemPluginInfo *info)
+static void
+totem_plugins_engine_finalize (GObject *object)
 {
-	g_return_val_if_fail (info != NULL, NULL);
+	TotemPluginsEngine *engine = TOTEM_PLUGINS_ENGINE (object);
 
-	return info->desc;
-}
-
-const gchar **
-totem_plugins_engine_get_plugin_authors (TotemPluginInfo *info)
-{
-	g_return_val_if_fail (info != NULL, (const gchar **)NULL);
+	if (engine->priv->totem) {
+		peas_extension_set_call (engine->priv->activatable_extensions,
+					 "deactivate", engine->priv->totem);
 
-	return (const gchar **)info->authors;
-}
+		g_object_unref (engine->priv->totem);
+		engine->priv->totem = NULL;
+	}
 
-const gchar *
-totem_plugins_engine_get_plugin_website (TotemPluginInfo *info)
-{
-	g_return_val_if_fail (info != NULL, NULL);
+	if (engine->priv->garbage_collect_id > 0)
+		g_source_remove (engine->priv->garbage_collect_id);
+	engine->priv->garbage_collect_id = 0;
+	peas_engine_garbage_collect (PEAS_ENGINE (engine));
 
-	return info->website;
-}
+	if (engine->priv->notification_id > 0)
+		gconf_client_notify_remove (engine->priv->client,
+					    engine->priv->notification_id);
+	engine->priv->notification_id = 0;
 
-const gchar *
-totem_plugins_engine_get_plugin_copyright (TotemPluginInfo *info)
-{
-	g_return_val_if_fail (info != NULL, NULL);
+	if (engine->priv->client != NULL)
+		g_object_unref (engine->priv->client);
+	engine->priv->client = NULL;
 
-	return info->copyright;
+	G_OBJECT_CLASS (totem_plugins_engine_parent_class)->finalize (object);
 }
 
-GdkPixbuf *
-totem_plugins_engine_get_plugin_icon (TotemPluginInfo *info)
+static void
+totem_plugins_engine_gconf_cb (GConfClient *gconf_client,
+			       guint cnxn_id,
+			       GConfEntry *entry,
+			       TotemPluginsEngine *engine)
 {
-	if (info->icon_name == NULL)
-		return NULL;
+	char *plugin_name;
+	char *action_name;
+	PeasPluginInfo *info;
 
-	if (info->icon_pixbuf == NULL) {
-		char *filename = NULL;
-		char *dirname;
+	plugin_name = g_path_get_dirname (gconf_entry_get_key (entry));
+	info = peas_engine_get_plugin_info (PEAS_ENGINE (engine), plugin_name);
+	g_free (plugin_name);
 
-		dirname = g_path_get_dirname (info->file);
-		filename = g_build_filename (dirname, info->icon_name, NULL);
-		g_free (dirname);
+	if (info == NULL)
+		return;
+
+	action_name = g_path_get_basename (gconf_entry_get_key (entry));
+       //FIXME do some checks here
 
-		info->icon_pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
-		g_free (filename);
+	if (g_str_equal (action_name, "active") != FALSE) {
+		if (gconf_value_get_bool (entry->value)) {
+			peas_engine_activate_plugin (PEAS_ENGINE (engine), info);
+		} else {
+			peas_engine_deactivate_plugin (PEAS_ENGINE (engine), info);
+		}
+	} else if (g_str_equal (action_name, "hidden") != FALSE) {
+		peas_plugin_info_set_visible (info, !gconf_value_get_bool (entry->value));
 	}
 
-	return info->icon_pixbuf;
+	g_free (action_name);
 }
+
diff --git a/src/plugins/totem-plugins-engine.h b/src/plugins/totem-plugins-engine.h
index ce376db..2bdc495 100644
--- a/src/plugins/totem-plugins-engine.h
+++ b/src/plugins/totem-plugins-engine.h
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Plugin engine for Totem, heavily based on the code from Rhythmbox,
- * which is based heavily on the code from gedit.
+ * which is based heavily on the code from totem.
  *
  * Copyright (C) 2002-2005 Paolo Maggi
  *               2006 James Livingston  <jrl ids org au>
@@ -31,35 +31,37 @@
 #define __TOTEM_PLUGINS_ENGINE_H__
 
 #include <glib.h>
+#include <libpeas/peas-engine.h>
 #include <totem.h>
 
-typedef struct _TotemPluginInfo TotemPluginInfo;
+G_BEGIN_DECLS
 
-gboolean	 totem_plugins_engine_init 		(TotemObject *totem);
-void		 totem_plugins_engine_shutdown 		(void);
+#define TOTEM_TYPE_PLUGINS_ENGINE              (totem_plugins_engine_get_type ())
+#define TOTEM_PLUGINS_ENGINE(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), TOTEM_TYPE_PLUGINS_ENGINE, TotemPluginsEngine))
+#define TOTEM_PLUGINS_ENGINE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), TOTEM_TYPE_PLUGINS_ENGINE, TotemPluginsEngineClass))
+#define TOTEM_IS_PLUGINS_ENGINE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), TOTEM_TYPE_PLUGINS_ENGINE))
+#define TOTEM_IS_PLUGINS_ENGINE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_PLUGINS_ENGINE))
+#define TOTEM_PLUGINS_ENGINE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), TOTEM_TYPE_PLUGINS_ENGINE, TotemPluginsEngineClass))
 
-void		 totem_plugins_engine_garbage_collect	(void);
+typedef struct _TotemPluginsEngine		TotemPluginsEngine;
+typedef struct _TotemPluginsEnginePrivate	TotemPluginsEnginePrivate;
+typedef struct _TotemPluginsEngineClass		TotemPluginsEngineClass;
 
-GList*		totem_plugins_engine_get_plugins_list 	(void);
+struct _TotemPluginsEngine
+{
+	PeasEngine parent;
+	TotemPluginsEnginePrivate *priv;
+};
 
-gboolean 	 totem_plugins_engine_activate_plugin 	(TotemPluginInfo *info);
-gboolean 	 totem_plugins_engine_deactivate_plugin	(TotemPluginInfo *info);
-gboolean 	 totem_plugins_engine_plugin_is_active 	(TotemPluginInfo *info);
-gboolean 	 totem_plugins_engine_plugin_is_visible (TotemPluginInfo *info);
+struct _TotemPluginsEngineClass
+{
+	PeasEngineClass parent_class;
+};
 
-gboolean	 totem_plugins_engine_plugin_is_configurable
-							(TotemPluginInfo *info);
-void	 	 totem_plugins_engine_configure_plugin	(TotemPluginInfo *info,
-							 GtkWindow *parent);
+GType			totem_plugins_engine_get_type			(void) G_GNUC_CONST;
+TotemPluginsEngine	*totem_plugins_engine_get_default		(TotemObject *totem);
 
-const gchar*	totem_plugins_engine_get_plugin_name	(TotemPluginInfo *info);
-const gchar*	totem_plugins_engine_get_plugin_description
-							(TotemPluginInfo *info);
-
-const gchar**	totem_plugins_engine_get_plugin_authors	(TotemPluginInfo *info);
-const gchar*	totem_plugins_engine_get_plugin_website	(TotemPluginInfo *info);
-const gchar*	totem_plugins_engine_get_plugin_copyright
-							(TotemPluginInfo *info);
-GdkPixbuf *	totem_plugins_engine_get_plugin_icon	(TotemPluginInfo *info);
+G_END_DECLS
 
 #endif  /* __TOTEM_PLUGINS_ENGINE_H__ */
+
diff --git a/src/plugins/tracker/Makefile.am b/src/plugins/tracker/Makefile.am
index 3a0af32..4cd0d05 100644
--- a/src/plugins/tracker/Makefile.am
+++ b/src/plugins/tracker/Makefile.am
@@ -28,6 +28,7 @@ libtracker_la_CPPFLAGS = $(common_defines)
 
 libtracker_la_CFLAGS = \
 	$(DEPENDENCY_CFLAGS)	\
+	$(PEAS_CFLAGS)		\
 	$(TRACKER_CFLAGS)	\
 	$(WARN_CFLAGS)		\
 	$(DBUS_CFLAGS)		\
diff --git a/src/plugins/tracker/totem-tracker.c b/src/plugins/tracker/totem-tracker.c
index 70d545d..2250e47 100644
--- a/src/plugins/tracker/totem-tracker.c
+++ b/src/plugins/tracker/totem-tracker.c
@@ -60,7 +60,7 @@ typedef struct
 G_MODULE_EXPORT GType register_totem_plugin		(GTypeModule *module);
 GType	totem_tracker_plugin_get_type			(void) G_GNUC_CONST;
 
-static gboolean impl_activate				(TotemPlugin *plugin, TotemObject *totem, GError **error);
+static void impl_activate				(TotemPlugin *plugin, TotemObject *totem);
 static void impl_deactivate				(TotemPlugin *plugin, TotemObject *totem);
 
 TOTEM_PLUGIN_REGISTER (TotemTrackerPlugin, totem_tracker_plugin)
@@ -68,10 +68,10 @@ TOTEM_PLUGIN_REGISTER (TotemTrackerPlugin, totem_tracker_plugin)
 static void
 totem_tracker_plugin_class_init (TotemTrackerPluginClass *klass)
 {
-	TotemPluginClass *plugin_class = TOTEM_PLUGIN_CLASS (klass);
+	PeasPluginClass *plugin_class = PEAS_PLUGIN_CLASS (klass);
 
-	plugin_class->activate = impl_activate;
-	plugin_class->deactivate = impl_deactivate;
+	plugin_class->activate = (PeasFunc) impl_activate;
+	plugin_class->deactivate = (PeasFunc) impl_deactivate;
 }
 
 static void
@@ -79,18 +79,15 @@ totem_tracker_plugin_init (TotemTrackerPlugin *plugin)
 {
 }
 
-static gboolean
+static void
 impl_activate (TotemPlugin *plugin,
-	       TotemObject *totem,
-	       GError **error)
+	       TotemObject *totem)
 {
 	GtkWidget *widget;
 
 	widget = totem_tracker_widget_new (totem);
 	gtk_widget_show (widget);
 	totem_add_sidebar_page (totem, "tracker", _("Local Search"), widget);
-
-	return TRUE;
 }
 
 static void
diff --git a/src/plugins/youtube/Makefile.am b/src/plugins/youtube/Makefile.am
index c12af21..574ad6c 100644
--- a/src/plugins/youtube/Makefile.am
+++ b/src/plugins/youtube/Makefile.am
@@ -31,6 +31,7 @@ libyoutube_la_CPPFLAGS = $(common_defines)
 
 libyoutube_la_CFLAGS = \
 	$(DEPENDENCY_CFLAGS)	\
+	$(PEAS_CFLAGS)		\
 	$(LIBGDATA_CFLAGS)	\
 	$(WARN_CFLAGS)		\
 	$(DBUS_CFLAGS)		\
diff --git a/src/plugins/youtube/totem-youtube.c b/src/plugins/youtube/totem-youtube.c
index 61199bd..6fa5e18 100644
--- a/src/plugins/youtube/totem-youtube.c
+++ b/src/plugins/youtube/totem-youtube.c
@@ -89,7 +89,7 @@ typedef struct {
 G_MODULE_EXPORT GType register_totem_plugin	(GTypeModule *module);
 GType totem_youtube_plugin_get_type		(void) G_GNUC_CONST;
 
-static gboolean impl_activate			(TotemPlugin *plugin, TotemObject *totem, GError **error);
+static void impl_activate			(TotemPlugin *plugin, TotemObject *totem);
 static void impl_deactivate			(TotemPlugin *plugin, TotemObject *totem);
 
 /* GtkBuilder callbacks */
@@ -108,10 +108,10 @@ TOTEM_PLUGIN_REGISTER (TotemYouTubePlugin, totem_youtube_plugin)
 static void
 totem_youtube_plugin_class_init (TotemYouTubePluginClass *klass)
 {
-	TotemPluginClass *plugin_class = TOTEM_PLUGIN_CLASS (klass);
+	PeasPluginClass *plugin_class = PEAS_PLUGIN_CLASS (klass);
 
-	plugin_class->activate = impl_activate;
-	plugin_class->deactivate = impl_deactivate;
+	plugin_class->activate = (PeasFunc) impl_activate;
+	plugin_class->deactivate = (PeasFunc) impl_deactivate;
 }
 
 static void
@@ -332,8 +332,8 @@ set_up_tree_view (TotemYouTubePlugin *self, GtkBuilder *builder, guint key)
 	self->cancel_button = GTK_WIDGET (gtk_builder_get_object (builder, "yt_cancel_button"));
 }
 
-static gboolean
-impl_activate (TotemPlugin *plugin, TotemObject *totem, GError **error)
+static void
+impl_activate (TotemPlugin *plugin, TotemObject *totem)
 {
 	TotemYouTubePlugin *self = TOTEM_YOUTUBE_PLUGIN (plugin);
 	GtkWindow *main_window;
@@ -363,8 +363,6 @@ impl_activate (TotemPlugin *plugin, TotemObject *totem, GError **error)
 	/* Add the sidebar page */
 	totem_add_sidebar_page (totem, "youtube", _("YouTube"), self->vbox);
 	g_object_unref (builder);
-
-	return TRUE;
 }
 
 static void
diff --git a/src/totem-interface.c b/src/totem-interface.c
index c877cb6..e10782b 100644
--- a/src/totem-interface.c
+++ b/src/totem-interface.c
@@ -47,7 +47,6 @@
 #include <gconf/gconf-client.h>
 
 #include "totem-interface.h"
-#include "totem-private.h"
 
 static GtkWidget *
 totem_interface_error_dialog (const char *title, const char *reason,
@@ -129,14 +128,13 @@ totem_interface_error_blocking (const char *title, const char *reason,
  * @uri: the URI to open
  * @label: a label for the URI's button, or %NULL to use @uri as the label
  * @parent: the error dialogue's parent #GtkWindow
- * @totem: a #TotemObject
  *
  * Display a modal error dialogue like totem_interface_error(),
  * but add a button which will open @uri in a browser window.
  **/
 void
 totem_interface_error_with_link (const char *title, const char *reason,
-				 const char *uri, const char *label, GtkWindow *parent, Totem *totem)
+				 const char *uri, const char *label, GtkWindow *parent)
 {
 	GtkWidget *error_dialog, *link_button, *hbox;
 
diff --git a/src/totem-interface.h b/src/totem-interface.h
index a87e94a..f4c374b 100644
--- a/src/totem-interface.h
+++ b/src/totem-interface.h
@@ -48,8 +48,7 @@ void		 totem_interface_error_with_link (const char *title,
 						  const char *reason,
 						  const char *uri,
 						  const char *label,
-						  GtkWindow *parent,
-						  Totem *totem);
+						  GtkWindow *parent);
 void		 totem_interface_set_transient_for (GtkWindow *window,
 						    GtkWindow *parent);
 char *		 totem_interface_get_license	(void);
diff --git a/src/totem-menu.c b/src/totem-menu.c
index 5a9cca7..7e3b56a 100644
--- a/src/totem-menu.c
+++ b/src/totem-menu.c
@@ -26,6 +26,7 @@
 #include <glib/gi18n.h>
 #include <gst/tag/tag.h>
 #include <string.h>
+#include <libpeasui/peas-ui-plugin-manager.h>
 
 #include "totem-menu.h"
 #include "totem.h"
@@ -33,7 +34,6 @@
 #include "totem-private.h"
 #include "totem-sidebar.h"
 #include "totem-statusbar.h"
-#include "totem-plugin-manager.h"
 #include "bacon-video-widget.h"
 #include "totem-uri.h"
 
@@ -1234,7 +1234,7 @@ plugins_action_callback (GtkAction *action, Totem *totem)
 					 G_CALLBACK (totem_plugins_response_cb),
 					 NULL, 0);
 
-		manager = totem_plugin_manager_new ();
+		manager = peas_ui_plugin_manager_new (PEAS_ENGINE (totem->engine));
 		gtk_widget_show_all (GTK_WIDGET (manager));
 		gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (totem->plugins))),
 				   manager);
diff --git a/src/totem-object.c b/src/totem-object.c
index 31a2d41..80494b3 100644
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -333,7 +333,8 @@ totem_object_get_property (GObject *object,
 void
 totem_object_plugins_init (TotemObject *totem)
 {
-	totem_plugins_engine_init (totem);
+	if (totem->engine == NULL)
+		totem->engine = totem_plugins_engine_get_default (totem);
 }
 
 /**
@@ -343,9 +344,12 @@ totem_object_plugins_init (TotemObject *totem)
  * plugins.
  **/
 void
-totem_object_plugins_shutdown (void)
+totem_object_plugins_shutdown (TotemObject *totem)
 {
-	totem_plugins_engine_shutdown ();
+	if (totem->engine != NULL) {
+		g_object_unref (totem->engine);
+		totem->engine = NULL;
+	}
 }
 
 /**
@@ -962,7 +966,7 @@ totem_action_exit (Totem *totem)
 	/* Save the page ID before we close the plugins, otherwise
 	 * we'll never save it properly */
 	page_id = totem_sidebar_get_current_page (totem);
-	totem_object_plugins_shutdown ();
+	totem_object_plugins_shutdown (totem);
 
 	if (display != NULL)
 		gdk_display_sync (display);
@@ -1251,7 +1255,7 @@ totem_action_load_media (Totem *totem, TotemDiscMediaType type, const char *devi
 			g_assert_not_reached ();
 		}
 
-		totem_interface_error_with_link (msg, secondary, link, link_text, GTK_WINDOW (totem->win), totem);
+		totem_interface_error_with_link (msg, secondary, link, link_text, GTK_WINDOW (totem->win));
 		g_free (msg);
 		return FALSE;
 	}
diff --git a/src/totem-private.h b/src/totem-private.h
index 9d5b89c..660c53f 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -37,6 +37,7 @@
 #include "bacon-video-widget.h"
 #include "totem-open-location.h"
 #include "totem-fullscreen.h"
+#include "totem-plugins-engine.h"
 
 #define totem_signal_block_by_data(obj, data) (g_signal_handlers_block_matched (obj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data))
 #define totem_signal_unblock_by_data(obj, data) (g_signal_handlers_unblock_matched (obj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data))
@@ -95,6 +96,7 @@ struct _TotemObject {
 
 	/* Plugins */
 	GtkWidget *plugins;
+	TotemPluginsEngine *engine;
 
 	/* Sidebar */
 	GtkWidget *sidebar;
diff --git a/src/totem.h b/src/totem.h
index 959e40e..8af9c30 100644
--- a/src/totem.h
+++ b/src/totem.h
@@ -181,7 +181,7 @@ typedef struct {
 
 GType	totem_object_get_type			(void);
 void    totem_object_plugins_init		(TotemObject *totem);
-void    totem_object_plugins_shutdown		(void);
+void    totem_object_plugins_shutdown		(TotemObject *totem);
 void	totem_file_opened			(TotemObject *totem,
 						 const char *mrl);
 void	totem_file_closed			(TotemObject *totem);



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