diff options
author | Bastien Nocera <hadess@hadess.net> | 2010-06-15 17:10:52 +0100 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2010-06-16 18:18:59 +0100 |
commit | 7bf399f1365f8e9f76edb08007b10a9c756f650b (patch) | |
tree | ab736fed739b8f8ace84ae9b52e294cfe686d809 /src | |
parent | dc894da891c37c30b0acb648da9d49e2bc9c6d61 (diff) | |
download | totem-7bf399f1365f8e9f76edb08007b10a9c756f650b.tar.gz |
Port to libpeas for plugin handling
https://bugzilla.gnome.org/show_bug.cgi?id=604830
Diffstat (limited to 'src')
25 files changed, 459 insertions, 2541 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b9194a8bc..5b82995e7 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 25abd3083..e4feb24cb 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 000000000..4209096e6 --- /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 index 442e3e9e7..57ce86076 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-module.c b/src/plugins/totem-module.c deleted file mode 100644 index 1ca311927..000000000 --- a/src/plugins/totem-module.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This is a based on rb-module.c from Rhythmbox, which is based on - * gedit-module.h from gedit, which is based on Epiphany source code. - * - * Copyright (C) 2003 Marco Pesenti Gritti - * Copyright (C) 2003, 2004 Christian Persch - * Copyright (C) 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. - * - */ - -#include "config.h" - -#include "totem-module.h" - -#include <gmodule.h> - -typedef struct _TotemModuleClass TotemModuleClass; - -struct _TotemModuleClass -{ - GTypeModuleClass parent_class; -}; - -struct _TotemModule -{ - GTypeModule parent_instance; - - GModule *library; - - gchar *path; - gchar *name; - GType type; -}; - -typedef GType (*TotemModuleRegisterFunc) (GTypeModule *); - -static GObjectClass *parent_class = NULL; - -G_DEFINE_TYPE (TotemModule, totem_module, G_TYPE_TYPE_MODULE) - -static gboolean -totem_module_load (GTypeModule *gmodule) -{ - TotemModule *module = TOTEM_MODULE (gmodule); - TotemModuleRegisterFunc register_func; - - module->library = g_module_open (module->path, 0); - - if (module->library == NULL) { - g_warning ("%s", g_module_error()); - return FALSE; - } - - /* extract symbols from the lib */ - if (!g_module_symbol (module->library, "register_totem_plugin", (void *)®ister_func)) { - g_warning ("%s", g_module_error ()); - g_module_close (module->library); - return FALSE; - } - - g_assert (register_func); - - module->type = register_func (gmodule); - if (module->type == 0) { - g_warning ("Invalid totem plugin contained by module %s", module->path); - return FALSE; - } - - return TRUE; -} - -static void -totem_module_unload (GTypeModule *gmodule) -{ - TotemModule *module = TOTEM_MODULE (gmodule); - - g_module_close (module->library); - - module->library = NULL; - module->type = 0; -} - -const gchar * -totem_module_get_path (TotemModule *module) -{ - g_return_val_if_fail (TOTEM_IS_MODULE (module), NULL); - - return module->path; -} - -GObject * -totem_module_new_object (TotemModule *module) -{ - GObject *obj; - - if (module->type == 0) { - return NULL; - } - - obj = g_object_new (module->type, - "name", module->name, - NULL); - return obj; -} - -static void -totem_module_init (TotemModule *module) -{ - -} - -static void -totem_module_finalize (GObject *object) -{ - TotemModule *module = TOTEM_MODULE (object); - - g_free (module->path); - g_free (module->name); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -totem_module_class_init (TotemModuleClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); - - parent_class = (GObjectClass *) g_type_class_peek_parent (class); - - object_class->finalize = totem_module_finalize; - - module_class->load = totem_module_load; - module_class->unload = totem_module_unload; -} - -TotemModule * -totem_module_new (const gchar *path, const char *module) -{ - TotemModule *result; - - if (path == NULL || path[0] == '\0') { - return NULL; - } - - result = g_object_new (TOTEM_TYPE_MODULE, NULL); - - g_type_module_set_name (G_TYPE_MODULE (result), path); - result->path = g_strdup (path); - result->name = g_strdup (module); - - return result; -} - diff --git a/src/plugins/totem-module.h b/src/plugins/totem-module.h deleted file mode 100644 index d485f40d1..000000000 --- a/src/plugins/totem-module.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This is a based on rb-module.h from Rhythmbox, which is based on - * gedit-module.h from gedit, which is based on Epiphany source code. - * - * Copyright (C) 2003 Marco Pesenti Gritti - * Copyright (C) 2003, 2004 Christian Persch - * Copyright (C) 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. - * - */ - -#ifndef TOTEM_MODULE_H -#define TOTEM_MODULE_H - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TOTEM_TYPE_MODULE (totem_module_get_type ()) -#define TOTEM_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_MODULE, TotemModule)) -#define TOTEM_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_MODULE, TotemModuleClass)) -#define TOTEM_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_MODULE)) -#define TOTEM_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TOTEM_TYPE_MODULE)) -#define TOTEM_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TOTEM_TYPE_MODULE, TotemModuleClass)) - -typedef struct _TotemModule TotemModule; - -GType totem_module_get_type (void) G_GNUC_CONST;; - -TotemModule *totem_module_new (const gchar *path, const char *module); - -const gchar *totem_module_get_path (TotemModule *module); - -GObject *totem_module_new_object (TotemModule *module); - -G_END_DECLS - -#endif diff --git a/src/plugins/totem-plugin-manager.c b/src/plugins/totem-plugin-manager.c deleted file mode 100644 index 26331b021..000000000 --- a/src/plugins/totem-plugin-manager.c +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * heavily based on code from Rhythmbox and Gedit - * - * Copyright (C) 2002 Paolo Maggi and James Willcox - * Copyright (C) 2003-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 <string.h> - -#include <glib/gi18n.h> -#include <gtk/gtk.h> - -#include "totem-interface.h" -#include "totem-plugin-manager.h" -#include "totem-plugins-engine.h" -#include "totem-plugin.h" - -enum -{ - ACTIVE_COLUMN, - VISIBLE_COLUMN, - INFO_COLUMN, - N_COLUMNS -}; - -#define PLUGIN_MANAGER_NAME_TITLE _("Plugin") -#define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled") - -#define TOTEM_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), TOTEM_TYPE_PLUGIN_MANAGER, TotemPluginManagerPrivate)) - -struct _TotemPluginManagerPrivate -{ - GList *plugins; - GtkWidget *tree; - GtkTreeModel *plugin_model; - - GtkWidget *configure_button; - GtkWidget *header_hbox; - GtkWidget *plugin_icon; - GtkWidget *site_text; - GtkWidget *copyright_text; - GtkWidget *authors_text; - GtkWidget *description_text; - GtkWidget *plugin_title; -}; - -G_DEFINE_TYPE(TotemPluginManager, totem_plugin_manager, GTK_TYPE_VBOX) - -static void totem_plugin_manager_finalize (GObject *o); -static TotemPluginInfo *plugin_manager_get_selected_plugin (TotemPluginManager *pm); -static void plugin_manager_toggle_active (GtkTreeIter *iter, GtkTreeModel *model, TotemPluginManager *pm); -static void plugin_manager_toggle_all (TotemPluginManager *pm); - -/* Callback functions for GtkBuilder */ -G_MODULE_EXPORT void configure_button_cb (GtkWidget *button, TotemPluginManager *pm); - -static void -totem_plugin_manager_class_init (TotemPluginManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = totem_plugin_manager_finalize; - - g_type_class_add_private (object_class, sizeof (TotemPluginManagerPrivate)); -} - -void -configure_button_cb (GtkWidget *button, - TotemPluginManager *pm) -{ - TotemPluginInfo *info; - GtkWindow *toplevel; - - info = plugin_manager_get_selected_plugin (pm); - - g_return_if_fail (info != NULL); - - toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (pm))); - - totem_plugins_engine_configure_plugin (info, toplevel); -} - -static void -plugin_manager_view_cell_cb (GtkTreeViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer data) -{ - TotemPluginInfo *info; - - g_return_if_fail (tree_model != NULL); - g_return_if_fail (tree_column != NULL); - - gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1); - - if (info == NULL) - return; - - g_return_if_fail (totem_plugins_engine_get_plugin_name (info) != NULL); - - g_object_set (G_OBJECT (cell), - "text", - totem_plugins_engine_get_plugin_name (info), - NULL); -} - -static void -active_toggled_cb (GtkCellRendererToggle *cell, - gchar *path_str, - TotemPluginManager *pm) -{ - GtkTreeIter iter; - GtkTreePath *path; - GtkTreeModel *model; - - path = gtk_tree_path_new_from_string (path_str); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); - g_return_if_fail (model != NULL); - - if (gtk_tree_model_get_iter (model, &iter, path)) - plugin_manager_toggle_active (&iter, model, pm); - - gtk_tree_path_free (path); -} - -static void -cursor_changed_cb (GtkTreeSelection *selection, - gpointer data) -{ - TotemPluginManager *pm = data; - GtkTreeView *view; - TotemPluginInfo *info; - char *string; - GdkPixbuf *icon; - - view = gtk_tree_selection_get_tree_view (selection); - info = plugin_manager_get_selected_plugin (pm); - - if (info == NULL) - return; - - /* update info widgets */ - string = g_strdup_printf ("<span size=\"x-large\">%s</span>", - totem_plugins_engine_get_plugin_name (info)); - gtk_label_set_markup (GTK_LABEL (pm->priv->plugin_title), string); - g_free (string); - gtk_label_set_text (GTK_LABEL (pm->priv->description_text), - totem_plugins_engine_get_plugin_description (info)); - gtk_label_set_text (GTK_LABEL (pm->priv->copyright_text), - totem_plugins_engine_get_plugin_copyright (info)); - gtk_label_set_text (GTK_LABEL (pm->priv->site_text), - totem_plugins_engine_get_plugin_website (info)); - - string = g_strjoinv ("\n", (gchar**)totem_plugins_engine_get_plugin_authors (info)); - gtk_label_set_text (GTK_LABEL (pm->priv->authors_text), string); - g_free (string); - - icon = totem_plugins_engine_get_plugin_icon (info); - if (icon != NULL) { - /* rescale icon to fit header if needed */ - GdkPixbuf *icon_scaled; - gint width, height, header_height; - GtkAllocation allocation; - - width = gdk_pixbuf_get_width (icon); - height = gdk_pixbuf_get_height (icon); - gtk_widget_get_allocation (pm->priv->header_hbox, &allocation); - header_height = allocation.height; - if (height > header_height) { - icon_scaled = gdk_pixbuf_scale_simple (icon, - (gfloat)width/height*header_height, header_height, - GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf (GTK_IMAGE (pm->priv->plugin_icon), icon_scaled); - g_object_unref (G_OBJECT (icon_scaled)); - } else { - gtk_image_set_from_pixbuf (GTK_IMAGE (pm->priv->plugin_icon), icon); - } - } else { - gtk_image_set_from_pixbuf (GTK_IMAGE (pm->priv->plugin_icon), NULL); - } - - gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button), - (info != NULL) && - totem_plugins_engine_plugin_is_configurable (info)); -} - -static void -row_activated_cb (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer data) -{ - TotemPluginManager *pm = data; - GtkTreeIter iter; - GtkTreeModel *model; - gboolean found; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); - g_return_if_fail (model != NULL); - - found = gtk_tree_model_get_iter (model, &iter, path); - g_return_if_fail (found); - - plugin_manager_toggle_active (&iter, model, pm); -} - -static void -column_clicked_cb (GtkTreeViewColumn *tree_column, - gpointer data) -{ - TotemPluginManager *pm = TOTEM_PLUGIN_MANAGER (data); - - plugin_manager_toggle_all (pm); -} - -static void -plugin_manager_populate_lists (TotemPluginManager *pm) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GList *p; - - for (p = pm->priv->plugins; p != NULL; p = g_list_next (p)) { - TotemPluginInfo *info; - info = (TotemPluginInfo *)p->data; - - gtk_list_store_append (GTK_LIST_STORE (pm->priv->plugin_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (pm->priv->plugin_model), &iter, - ACTIVE_COLUMN, totem_plugins_engine_plugin_is_active (info), - VISIBLE_COLUMN, totem_plugins_engine_plugin_is_visible (info), - INFO_COLUMN, info, - -1); - } - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) { - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)); - g_return_if_fail (selection != NULL); - - gtk_tree_selection_select_iter (selection, &iter); - } -} - -static void -plugin_manager_set_active (GtkTreeIter *iter, - GtkTreeModel *model, - gboolean active, - TotemPluginManager *pm) -{ - TotemPluginInfo *info; - GtkTreeIter child_iter; - - gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1); - - g_return_if_fail (info != NULL); - - if (active) { - /* activate the plugin */ - if (!totem_plugins_engine_activate_plugin (info)) { - active ^= 1; - } - } else { - /* deactivate the plugin */ - if (!totem_plugins_engine_deactivate_plugin (info)) { - active ^= 1; - } - } - - /* set new value */ - gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), - &child_iter, iter); - gtk_list_store_set (GTK_LIST_STORE (pm->priv->plugin_model), - &child_iter, - ACTIVE_COLUMN, - totem_plugins_engine_plugin_is_active (info), - -1); - - /* cause the configure button sensitivity to be updated */ - cursor_changed_cb (gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)), pm); -} - -static void -plugin_manager_toggle_active (GtkTreeIter *iter, - GtkTreeModel *model, - TotemPluginManager *pm) -{ - gboolean active, visible; - - gtk_tree_model_get (model, iter, - ACTIVE_COLUMN, &active, - VISIBLE_COLUMN, &visible, - -1); - - if (visible) { - active ^= 1; - plugin_manager_set_active (iter, model, active, pm); - } -} - -static TotemPluginInfo * -plugin_manager_get_selected_plugin (TotemPluginManager *pm) -{ - TotemPluginInfo *info = NULL; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreeSelection *selection; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); - g_return_val_if_fail (model != NULL, NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)); - g_return_val_if_fail (selection != NULL, NULL); - - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { - gtk_tree_model_get (model, &iter, INFO_COLUMN, &info, -1); - } - - return info; -} - -static void -plugin_manager_toggle_all (TotemPluginManager *pm) -{ - GtkTreeModel *model; - GtkTreeIter iter; - static gboolean active; - - active ^= 1; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)); - - g_return_if_fail (model != NULL); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - do { - plugin_manager_set_active (&iter, model, active, pm); - } while (gtk_tree_model_iter_next (model, &iter)); - } -} - -/* Callback used as the interactive search comparison function */ -static gboolean -name_search_cb (GtkTreeModel *model, - gint column, - const gchar *key, - GtkTreeIter *iter, - gpointer data) -{ - TotemPluginInfo *info; - gchar *normalized_string; - gchar *normalized_key; - gchar *case_normalized_string; - gchar *case_normalized_key; - gint key_len; - gboolean retval; - - gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1); - if (!info) - return FALSE; - - normalized_string = g_utf8_normalize (totem_plugins_engine_get_plugin_name (info), -1, G_NORMALIZE_ALL); - normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL); - case_normalized_string = g_utf8_casefold (normalized_string, -1); - case_normalized_key = g_utf8_casefold (normalized_key, -1); - - key_len = strlen (case_normalized_key); - - /* Oddly enough, this callback must return whether to stop the search - * because we found a match, not whether we actually matched. - */ - retval = (strncmp (case_normalized_key, case_normalized_string, key_len) != 0); - - g_free (normalized_key); - g_free (normalized_string); - g_free (case_normalized_key); - g_free (case_normalized_string); - - return retval; -} - -static void -plugin_manager_construct_tree (TotemPluginManager *pm) -{ - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - GtkTreeModel *filter; - GtkTreeSelection *selection; - - pm->priv->plugin_model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_POINTER)); - filter = gtk_tree_model_filter_new (pm->priv->plugin_model, NULL); - gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), VISIBLE_COLUMN); - gtk_tree_view_set_model (GTK_TREE_VIEW (pm->priv->tree), filter); - g_object_unref (filter); - - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm->priv->tree), TRUE); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pm->priv->tree), TRUE); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - - /* first column */ - cell = gtk_cell_renderer_toggle_new (); - g_signal_connect (cell, - "toggled", - G_CALLBACK (active_toggled_cb), - pm); - column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE, - cell, - "active", - ACTIVE_COLUMN, - NULL); - gtk_tree_view_column_set_clickable (column, TRUE); - gtk_tree_view_column_set_resizable (column, TRUE); - g_signal_connect (column, "clicked", G_CALLBACK (column_clicked_cb), pm); - gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column); - - /* second column */ - cell = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_NAME_TITLE, cell, NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_cell_data_func (column, cell, plugin_manager_view_cell_cb, - pm, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column); - - /* Enable search for our non-string column */ - gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm->priv->tree), INFO_COLUMN); - gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm->priv->tree), - name_search_cb, - NULL, - NULL); - - g_signal_connect (selection, - "changed", - G_CALLBACK (cursor_changed_cb), - pm); - g_signal_connect (pm->priv->tree, - "row_activated", - G_CALLBACK (row_activated_cb), - pm); - - gtk_widget_show (pm->priv->tree); -} - -static int -plugin_name_cmp (gconstpointer a, gconstpointer b) -{ - TotemPluginInfo *lhs = (TotemPluginInfo*)a; - TotemPluginInfo *rhs = (TotemPluginInfo*)b; - return strcmp (totem_plugins_engine_get_plugin_name (lhs), - totem_plugins_engine_get_plugin_name (rhs)); -} - -static void -totem_plugin_manager_init (TotemPluginManager *pm) -{ - GtkBuilder *xml; - GtkWidget *plugins_window; - - pm->priv = TOTEM_PLUGIN_MANAGER_GET_PRIVATE (pm); - - xml = totem_interface_load ("plugins.ui", TRUE, NULL, pm); - - gtk_container_add (GTK_CONTAINER (pm), GTK_WIDGET (gtk_builder_get_object (xml, "plugins_vbox"))); - - gtk_box_set_spacing (GTK_BOX (pm), 6); - - pm->priv->tree = gtk_tree_view_new (); - plugins_window = GTK_WIDGET (gtk_builder_get_object (xml, "plugins_list_window")); - gtk_container_add (GTK_CONTAINER (plugins_window), pm->priv->tree); - - pm->priv->configure_button = GTK_WIDGET (gtk_builder_get_object (xml, "configure_button")); - pm->priv->header_hbox = GTK_WIDGET (gtk_builder_get_object (xml, "header_hbox")); - pm->priv->plugin_title = GTK_WIDGET (gtk_builder_get_object (xml, "plugin_title")); - - pm->priv->plugin_icon = GTK_WIDGET (gtk_builder_get_object (xml, "plugin_icon")); - pm->priv->site_text = GTK_WIDGET (gtk_builder_get_object (xml, "site_text")); - pm->priv->copyright_text = GTK_WIDGET (gtk_builder_get_object (xml, "copyright_text")); - pm->priv->authors_text = GTK_WIDGET (gtk_builder_get_object (xml, "authors_text")); - pm->priv->description_text = GTK_WIDGET (gtk_builder_get_object (xml, "description_text")); - - plugin_manager_construct_tree (pm); - - /* get the list of available plugins (or installed) */ - pm->priv->plugins = totem_plugins_engine_get_plugins_list (); - pm->priv->plugins = g_list_sort (pm->priv->plugins, plugin_name_cmp); - plugin_manager_populate_lists (pm); - g_object_unref (xml); -} - -GtkWidget * -totem_plugin_manager_new (void) -{ - return g_object_new (TOTEM_TYPE_PLUGIN_MANAGER, 0); -} - -static void -totem_plugin_manager_finalize (GObject *o) -{ - TotemPluginManager *pm = TOTEM_PLUGIN_MANAGER (o); - - g_list_free (pm->priv->plugins); - - G_OBJECT_CLASS (totem_plugin_manager_parent_class)->finalize (o); -} diff --git a/src/plugins/totem-plugin-manager.h b/src/plugins/totem-plugin-manager.h deleted file mode 100644 index 6db825b7c..000000000 --- a/src/plugins/totem-plugin-manager.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * heavily based on code from Rhythmbox and Gedit - * - * Copyright (C) 2002 Paolo Maggi and James Willcox - * Copyright (C) 2003-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. - * - */ - -#ifndef __TOTEM_PLUGIN_MANAGER_H__ -#define __TOTEM_PLUGIN_MANAGER_H__ - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -/* - * Type checking and casting macros - */ -#define TOTEM_TYPE_PLUGIN_MANAGER (totem_plugin_manager_get_type()) -#define TOTEM_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TOTEM_TYPE_PLUGIN_MANAGER, TotemPluginManager)) -#define TOTEM_PLUGIN_MANAGER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TOTEM_TYPE_PLUGIN_MANAGER, TotemPluginManager const)) -#define TOTEM_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TOTEM_TYPE_PLUGIN_MANAGER, TotemPluginManagerClass)) -#define TOTEM_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TOTEM_TYPE_PLUGIN_MANAGER)) -#define TOTEM_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_PLUGIN_MANAGER)) -#define TOTEM_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TOTEM_TYPE_PLUGIN_MANAGER, TotemPluginManagerClass)) - -/* Private structure type */ -typedef struct _TotemPluginManagerPrivate TotemPluginManagerPrivate; - -/* - * Main object structure - */ -typedef struct -{ - GtkVBox vbox; - - /*< private > */ - TotemPluginManagerPrivate *priv; -} TotemPluginManager; - -/* - * Class definition - */ -typedef struct -{ - GtkVBoxClass parent_class; -} TotemPluginManagerClass; - -/* - * Public methods - */ -GType totem_plugin_manager_get_type (void) G_GNUC_CONST; - -GtkWidget *totem_plugin_manager_new (void); - -G_END_DECLS - -#endif /* __TOTEM_PLUGIN_MANAGER_H__ */ diff --git a/src/plugins/totem-plugins-engine.c b/src/plugins/totem-plugins-engine.c index 16e3c33be..7972838b6 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 ce376dbbf..2bdc4954b 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/totem-python-module.c b/src/plugins/totem-python-module.c deleted file mode 100644 index 7eee97cde..000000000 --- a/src/plugins/totem-python-module.c +++ /dev/null @@ -1,566 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Heavily based on code from Rhythmbox and Gedit. - * - * Copyright (C) 2005 Raphael Slinckx - * Copyright (C) 2007 Philip Withnall - * - * 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. - * - * Saturday 19th May 2007: Philip Withnall: 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> - -#include <signal.h> - -#include <gmodule.h> - -#include "totem-plugin.h" -#include "totem-python-module.h" -#include "totem-python-plugin.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 - -#define TOTEM_PYTHON_MODULE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \ - TOTEM_TYPE_PYTHON_MODULE, \ - TotemPythonModulePrivate)) - -typedef struct -{ - gchar *module; - gchar *path; - GType type; -} TotemPythonModulePrivate; - -enum -{ - PROP_0, - PROP_PATH, - PROP_MODULE -}; - -/* indicates whether all initializations in - * totem_python_module_init_python were successful */ -gboolean python_initialized = FALSE; - -#ifndef PYGOBJECT_CAN_MARSHAL_GVALUE -static PyObject * -pyg_value_g_value_as_pyobject (const GValue *value) -{ - return pyg_value_as_pyobject((GValue *)g_value_get_boxed(value), FALSE); -} - -static int -pyg_value_g_value_from_pyobject (GValue *value, PyObject *obj) -{ - GType type; - GValue obj_value = { 0, }; - - type = pyg_type_from_object((PyObject *) obj->ob_type); - if (! type) { - PyErr_Clear(); - return -1; - } - g_value_init(&obj_value, type); - if (pyg_value_from_pyobject(&obj_value, obj) == -1) { - g_value_unset(&obj_value); - return -1; - } - g_value_set_boxed(value, &obj_value); - g_value_unset(&obj_value); - return 0; -} -#endif /* PYGOBJECT_CAN_MARSHAL_GVALUE */ - -/* 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 retreive this to check for correct class hierarchy */ -static PyTypeObject *PyTotemPlugin_Type; - -G_DEFINE_TYPE (TotemPythonModule, totem_python_module, G_TYPE_TYPE_MODULE); - -static void -totem_python_module_init_python (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 }; - GList *paths; - - 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); - - /* pygtk.require("2.0") */ - pygtk = PyImport_ImportModule ("pygtk"); - if (pygtk == NULL) { - g_warning ("Could not import pygtk, check your installation"); - PyErr_Print(); - return; - } - - mdict = PyModule_GetDict (pygtk); - require = PyDict_GetItemString (mdict, "require"); - PyObject_CallObject (require, Py_BuildValue ("(S)", PyString_FromString ("2.0"))); - if (PyErr_Occurred ()) { - g_warning ("Could not get required pygtk version, check your installation"); - PyErr_Print(); - return; - } - - /* import gobject */ - init_pygobject (); - - /* disable pyg* log hooks, since ours is more interesting */ -#ifdef pyg_disable_warning_redirections - pyg_disable_warning_redirections (); -#endif -#ifndef PYGOBJECT_CAN_MARSHAL_GVALUE - pyg_register_gtype_custom (G_TYPE_VALUE, pyg_value_g_value_as_pyobject, pyg_value_g_value_from_pyobject); -#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, check your installation.", - PyString_AsString (PyObject_Repr (pygtk_required_version)), - PyString_AsString (PyObject_Repr (pygtk_version))); - Py_DECREF (pygtk_required_version); - return; - } - Py_DECREF (pygtk_required_version); - - /* import totem */ - paths = totem_get_plugin_paths (); - sys_path = PySys_GetObject ("path"); - while (paths != NULL) { - PyObject *path; - - path = PyString_FromString (paths->data); - if (PySequence_Contains (sys_path, path) == 0) { - PyList_Insert (sys_path, 0, path); - } - Py_DECREF (path); - g_free (paths->data); - paths = g_list_delete_link (paths, paths); - } - - totem = PyImport_ImportModule ("totem"); - - if (totem == NULL) { - g_warning ("Could not import Python module 'totem', check your installation"); - 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_"); - - /* Retreive 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(); - - /* Python and the supporting libraries were initialised - * successfully */ - python_initialized = TRUE; -} - -static gboolean -totem_python_module_load (GTypeModule *gmodule) -{ - TotemPythonModulePrivate *priv = TOTEM_PYTHON_MODULE_GET_PRIVATE (gmodule); - PyGILState_STATE state; - PyObject *main_module, *main_locals, *locals, *key, *value; - PyObject *module, *fromlist; - Py_ssize_t pos = 0; - gboolean res = FALSE; - - g_return_val_if_fail (Py_IsInitialized (), FALSE); - if (python_initialized == FALSE) - return FALSE; - - state = pyg_gil_state_ensure(); - - main_module = PyImport_AddModule ("__main__"); - if (main_module == NULL) - { - g_warning ("Could not get __main__."); - goto done; - } - - /* If we have a special path, we register it */ - if (priv->path != NULL) - { - PyObject *sys_path = PySys_GetObject ("path"); - PyObject *path = PyString_FromString (priv->path); - - if (PySequence_Contains(sys_path, path) == 0) - PyList_Insert (sys_path, 0, path); - - Py_DECREF(path); - } - - main_locals = PyModule_GetDict (main_module); - /* we need a fromlist to be able to import modules with a '.' in the - name. */ - fromlist = PyTuple_New(0); - module = PyImport_ImportModuleEx (priv->module, main_locals, - main_locals, fromlist); - Py_DECREF (fromlist); - if (!module) { - PyErr_Print (); - goto done; - } - - locals = PyModule_GetDict (module); - while (PyDict_Next (locals, &pos, &key, &value)) - { - if (!PyType_Check(value)) - continue; - - if (PyObject_IsSubclass (value, (PyObject*) PyTotemPlugin_Type)) - { - priv->type = totem_python_object_get_type (gmodule, value); - res = TRUE; - goto done; - } - } - - g_warning ("Failed to find any totem.Plugin-derived classes in Python plugin"); - -done: - - pyg_gil_state_release (state); - return res; -} - -static void -totem_python_module_unload (GTypeModule *module) -{ - TotemPythonModulePrivate *priv = TOTEM_PYTHON_MODULE_GET_PRIVATE (module); - g_debug ("Unloading Python module"); - - priv->type = 0; -} - -GObject * -totem_python_module_new_object (TotemPythonModule *module) -{ - TotemPythonModulePrivate *priv = TOTEM_PYTHON_MODULE_GET_PRIVATE (module); - TotemPythonObject *object; - - if (priv->type == 0) - return NULL; - - g_debug ("Creating object of type %s", g_type_name (priv->type)); - object = (TotemPythonObject*) (g_object_new (priv->type, - "name", priv->module, - NULL)); - if (object->instance == NULL) { - g_warning ("Could not instantiate Python object"); - return NULL; - } - - /* FIXME, HACK: this is a hack because the gobject object->instance references - * isn't the same gobject as we think it is. Which Causes Issues. - * - * This still has issues, notably that it isn't safe to call any totem.Plugin methods - * from python before we get here. - * - * The solution is to not have weird proxy objects. - */ - g_object_set (((PyGObject*)(object->instance))->obj, "name", priv->module, NULL); - - return G_OBJECT (object); -} - -static void -totem_python_module_init (TotemPythonModule *module) -{ - g_debug ("Init of Python module"); -} - -static void -totem_python_module_finalize (GObject *object) -{ - TotemPythonModulePrivate *priv = TOTEM_PYTHON_MODULE_GET_PRIVATE (object); - - if (priv && priv->type) { - g_debug ("Finalizing Python module %s", g_type_name (priv->type)); - - g_free (priv->module); - g_free (priv->path); - } - - G_OBJECT_CLASS (totem_python_module_parent_class)->finalize (object); -} - -static void -totem_python_module_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - /* no readable properties */ - g_return_if_reached (); -} - -static void -totem_python_module_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - TotemPythonModule *mod = TOTEM_PYTHON_MODULE (object); - - switch (prop_id) - { - case PROP_MODULE: - TOTEM_PYTHON_MODULE_GET_PRIVATE (mod)->module = g_value_dup_string (value); - break; - case PROP_PATH: - TOTEM_PYTHON_MODULE_GET_PRIVATE (mod)->path = g_value_dup_string (value); - break; - default: - g_return_if_reached (); - } -} - -static void -totem_python_module_class_init (TotemPythonModuleClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); - - object_class->finalize = totem_python_module_finalize; - object_class->get_property = totem_python_module_get_property; - object_class->set_property = totem_python_module_set_property; - - g_object_class_install_property - (object_class, - PROP_MODULE, - g_param_spec_string ("module", - "Module Name", - "The Python module to load for this plugin", - NULL, - G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, - PROP_PATH, - g_param_spec_string ("path", - "Path", - "The Python path to use when loading this module", - NULL, - G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (object_class, sizeof (TotemPythonModulePrivate)); - - module_class->load = totem_python_module_load; - module_class->unload = totem_python_module_unload; - - /* Init Python subsystem, this should happen only once - * in the process lifetime, and doing it here is OK since - * class_init is called once */ - totem_python_module_init_python (); -} - -TotemPythonModule * -totem_python_module_new (const gchar *path, - const gchar *module) -{ - TotemPythonModule *result; - gchar *dir; - - if (module == NULL || module[0] == '\0') - return NULL; - - dir = g_path_get_dirname (path); - result = g_object_new (TOTEM_TYPE_PYTHON_MODULE, - "module", module, - "path", dir, - NULL); - g_free (dir); - - g_type_module_set_name (G_TYPE_MODULE (result), module); - - return result; -} - -/* --- these are not module methods, they are here out of convenience --- */ - -#if 0 -static gint idle_garbage_collect_id = 0; - -static gboolean -run_gc (gpointer data) -{ - gboolean ret = (PyGC_Collect () != 0); - - if (!ret) - idle_garbage_collect_id = 0; - - return ret; -} -#endif - -void -totem_python_garbage_collect (void) -{ -#if 0 - if (Py_IsInitialized() && idle_garbage_collect_id == 0) { - idle_garbage_collect_id = g_idle_add (run_gc, NULL); - } -#endif -} - -#if 0 -static gboolean -finalise_collect_cb (gpointer data) -{ - while (PyGC_Collect ()) - ; - - /* Useful if Python is refusing to give up its shell reference for some reason. - PyRun_SimpleString ("import gc, gobject\nfor o in gc.get_objects():\n\tif isinstance(o, gobject.GObject):\n\t\tprint o, gc.get_referrers(o)"); - */ - - return TRUE; -} -#endif - -void -totem_python_shutdown (void) -{ -#if 0 - if (Py_IsInitialized ()) { - if (idle_garbage_collect_id != 0) { - g_source_remove (idle_garbage_collect_id); - idle_garbage_collect_id = 0; - } - - while (run_gc (NULL)) - /* loop */; - - /* This helps to force Python to give up its shell reference */ - g_idle_add (finalise_collect_cb, NULL); - - /* Disable for now, due to bug 334188 - Py_Finalize ();*/ - } -#endif -} diff --git a/src/plugins/totem-python-module.h b/src/plugins/totem-python-module.h deleted file mode 100644 index 31a90130c..000000000 --- a/src/plugins/totem-python-module.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Heavily based on code from Rhythmbox and Gedit. - * - * Copyright (C) 2005 Raphael Slinckx - * Copyright (C) 2007 Philip Withnall - * - * 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. - * - * Saturday 19th May 2007: Philip Withnall: Add exception clause. - * See license_change file for details. - */ - -#ifndef TOTEM_PYTHON_MODULE_H -#define TOTEM_PYTHON_MODULE_H - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TOTEM_TYPE_PYTHON_MODULE (totem_python_module_get_type ()) -#define TOTEM_PYTHON_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_PYTHON_MODULE, TotemPythonModule)) -#define TOTEM_PYTHON_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_PYTHON_MODULE, TotemPythonModuleClass)) -#define TOTEM_IS_PYTHON_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_PYTHON_MODULE)) -#define TOTEM_IS_PYTHON_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TOTEM_TYPE_PYTHON_MODULE)) -#define TOTEM_PYTHON_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TOTEM_TYPE_PYTHON_MODULE, TotemPythonModuleClass)) - -typedef struct -{ - GTypeModuleClass parent_class; -} TotemPythonModuleClass; - -typedef struct -{ - GTypeModule parent_instance; -} TotemPythonModule; - -GType totem_python_module_get_type (void); -TotemPythonModule *totem_python_module_new (const gchar* path, const gchar *module); -GObject *totem_python_module_new_object (TotemPythonModule *module); - -/* --- python utils --- */ -void totem_python_garbage_collect (void); -void totem_python_shutdown (void); - -G_END_DECLS - -#endif diff --git a/src/plugins/totem-python-plugin.c b/src/plugins/totem-python-plugin.c deleted file mode 100644 index 5457e2924..000000000 --- a/src/plugins/totem-python-plugin.c +++ /dev/null @@ -1,282 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Heavily based on code from Rhythmbox and Gedit. - * - * Copyright (C) 2005 Raphael Slinckx - * Copyright (C) 2007 Philip Withnall - * - * 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. - * - * Saturday 19th May 2007: Philip Withnall: Add exception clause. - * See license_change file for details. - */ - -#include <config.h> - -#include "totem-python-plugin.h" -#include "totem-plugin.h" - -#include <pygobject.h> -#include <string.h> - -static GObjectClass *parent_class; - -static PyObject * -call_python_method (TotemPythonObject *object, - TotemObject *totem, - gchar *method) -{ - PyGILState_STATE state; - PyObject *py_ret = NULL; - - state = pyg_gil_state_ensure(); - - g_return_val_if_fail (PyObject_HasAttrString (object->instance, method), NULL); - - if (totem == NULL) { - py_ret = PyObject_CallMethod (object->instance, - method, - NULL); - } else { - py_ret = PyObject_CallMethod (object->instance, - method, - "(N)", - pygobject_new (G_OBJECT (totem))); - } - - if (!py_ret) - PyErr_Print (); - - pyg_gil_state_release (state); - - return py_ret; -} - -static gboolean -check_py_object_is_gtk_widget (PyObject *py_obj) -{ - static PyTypeObject *_PyGtkWidget_Type = NULL; - PyGILState_STATE state; - gboolean res = FALSE; - - state = pyg_gil_state_ensure(); - - if (_PyGtkWidget_Type == NULL) { - PyObject *module; - - if ((module = PyImport_ImportModule ("gtk"))) { - PyObject *moddict = PyModule_GetDict (module); - _PyGtkWidget_Type = (PyTypeObject *) PyDict_GetItemString (moddict, "Widget"); - } - - if (_PyGtkWidget_Type == NULL) { - PyErr_SetString(PyExc_TypeError, "could not find python gtk widget type"); - PyErr_Print(); - res = FALSE; - goto done; - } - } - - res = PyObject_TypeCheck (py_obj, _PyGtkWidget_Type) ? TRUE : FALSE; - -done: - pyg_gil_state_release (state); - return res; -} - -static void -impl_deactivate (TotemPlugin *plugin, - TotemObject *totem) -{ - PyGILState_STATE state = pyg_gil_state_ensure (); - TotemPythonObject *object = (TotemPythonObject *)plugin; - - if (PyObject_HasAttrString (object->instance, "deactivate")) { - PyObject *py_ret = call_python_method (object, totem, "deactivate"); - - if (py_ret) { - Py_XDECREF (py_ret); - } - } else { - TOTEM_PLUGIN_CLASS (parent_class)->deactivate (plugin, totem); - } - - pyg_gil_state_release (state); -} - -static gboolean -impl_activate (TotemPlugin *plugin, - TotemObject *totem, - GError **error) -{ - PyGILState_STATE state = pyg_gil_state_ensure (); - TotemPythonObject *object = (TotemPythonObject *)plugin; - - if (PyObject_HasAttrString (object->instance, "activate")) { - PyObject *py_ret = call_python_method (object, totem, "activate"); - - if (py_ret) { - Py_XDECREF (py_ret); - } - } else { - TOTEM_PLUGIN_CLASS (parent_class)->activate (plugin, totem, error); - } - - pyg_gil_state_release (state); - - return TRUE; -} - -static GtkWidget * -impl_create_configure_dialog (TotemPlugin *plugin) -{ - PyGILState_STATE state = pyg_gil_state_ensure (); - TotemPythonObject *object = (TotemPythonObject *)plugin; - GtkWidget *ret = NULL; - - if (PyObject_HasAttrString (object->instance, "create_configure_dialog")) { - PyObject *py_ret = call_python_method (object, NULL, "create_configure_dialog"); - - if (py_ret) { - if (check_py_object_is_gtk_widget (py_ret)) { - ret = GTK_WIDGET (pygobject_get (py_ret)); - g_object_ref (ret); - } else { - PyErr_SetString(PyExc_TypeError, "return value for create_configure_dialog is not a GtkWidget"); - PyErr_Print(); - } - - Py_DECREF (py_ret); - } - } else { - ret = TOTEM_PLUGIN_CLASS (parent_class)->create_configure_dialog (plugin); - } - - pyg_gil_state_release (state); - return ret; -} - -static gboolean -impl_is_configurable (TotemPlugin *plugin) -{ - PyGILState_STATE state = pyg_gil_state_ensure (); - TotemPythonObject *object = (TotemPythonObject *) plugin; - PyObject *dict = object->instance->ob_type->tp_dict; - gboolean result; - - if (dict == NULL) - result = FALSE; - else if (!PyDict_Check(dict)) - result = FALSE; - else - result = PyDict_GetItemString(dict, "create_configure_dialog") != NULL; - - pyg_gil_state_release (state); - - return result; -} - -static void -totem_python_object_init (TotemPythonObject *object) -{ - TotemPythonObjectClass *class; - PyGILState_STATE state; - - state = pyg_gil_state_ensure(); - - g_debug ("Creating Python plugin instance"); - - class = (TotemPythonObjectClass*) (((GTypeInstance*) object)->g_class); - - object->instance = PyObject_CallObject (class->type, NULL); - if (object->instance == NULL) - PyErr_Print(); - - pyg_gil_state_release (state); -} - -static void -totem_python_object_finalize (GObject *object) -{ - g_debug ("Finalizing Python plugin instance"); - - if (((TotemPythonObject *) object)->instance) { - PyGILState_STATE state; - - state = pyg_gil_state_ensure(); - Py_DECREF (((TotemPythonObject *) object)->instance); - pyg_gil_state_release (state); - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -totem_python_object_class_init (TotemPythonObjectClass *klass, - gpointer class_data) -{ - TotemPluginClass *plugin_class = TOTEM_PLUGIN_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - klass->type = (PyObject*) class_data; - - object_class->finalize = totem_python_object_finalize; - - plugin_class->activate = impl_activate; - plugin_class->deactivate = impl_deactivate; - plugin_class->create_configure_dialog = impl_create_configure_dialog; - plugin_class->is_configurable = impl_is_configurable; -} - -GType -totem_python_object_get_type (GTypeModule *module, - PyObject *type) -{ - GType gtype; - gchar *type_name; - - GTypeInfo info = { - sizeof (TotemPythonObjectClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) totem_python_object_class_init, - NULL, /* class_finalize */ - type, /* class_data */ - sizeof (TotemPythonObject), - 0, /* n_preallocs */ - (GInstanceInitFunc) totem_python_object_init - }; - - /* no need for pyg_gil_state_ensure() here since this function is only - * used from within totem_python_module_load() where this is already - * done */ - - Py_INCREF (type); - - type_name = g_strdup_printf ("%s+TotemPythonPlugin", - PyString_AsString (PyObject_GetAttrString (type, "__name__"))); - - g_debug ("Registering Python plugin instance: %s", type_name); - gtype = g_type_module_register_type (module, - TOTEM_TYPE_PLUGIN, - type_name, - &info, 0); - g_free (type_name); - - return gtype; -} diff --git a/src/plugins/totem/Makefile.am b/src/plugins/totem/Makefile.am deleted file mode 100644 index 8e4f524e3..000000000 --- a/src/plugins/totem/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -plugindir = $(PLUGINDIR)/totem -plugin_PYTHON = \ - __init__.py - diff --git a/src/plugins/totem/__init__.py b/src/plugins/totem/__init__.py deleted file mode 100644 index c2845c69a..000000000 --- a/src/plugins/totem/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import gettext -gettext.textdomain("totem") - -D_ = gettext.dgettext -_ = gettext.gettext - diff --git a/src/plugins/tracker/Makefile.am b/src/plugins/tracker/Makefile.am index 3a0af32d5..4cd0d0560 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 70d545d07..2250e4796 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 c12af213c..574ad6c54 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 61199bd4e..6fa5e18f9 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 c877cb60d..e10782bd3 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 a87e94a52..f4c374bf6 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 5a9cca74e..7e3b56a05 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 31a2d4179..80494b35f 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 9d5b89c44..660c53fc3 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 959e40e0a..8af9c3049 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); |