summaryrefslogtreecommitdiff
path: root/mate-settings-daemon/mate-settings-plugin-info.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-settings-daemon/mate-settings-plugin-info.c')
-rw-r--r--mate-settings-daemon/mate-settings-plugin-info.c616
1 files changed, 616 insertions, 0 deletions
diff --git a/mate-settings-daemon/mate-settings-plugin-info.c b/mate-settings-daemon/mate-settings-plugin-info.c
new file mode 100644
index 0000000..c5cd494
--- /dev/null
+++ b/mate-settings-daemon/mate-settings-plugin-info.c
@@ -0,0 +1,616 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <[email protected]>
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gmodule.h>
+#include <mateconf/mateconf-client.h>
+
+#include "mate-settings-plugin-info.h"
+#include "mate-settings-module.h"
+#include "mate-settings-plugin.h"
+#include "mate-settings-profile.h"
+
+#define MATE_SETTINGS_PLUGIN_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MATE_TYPE_SETTINGS_PLUGIN_INFO, MateSettingsPluginInfoPrivate))
+
+#define PLUGIN_GROUP "MATE Settings Plugin"
+
+#define PLUGIN_PRIORITY_MAX 1
+#define PLUGIN_PRIORITY_DEFAULT 100
+
+typedef enum
+{
+ MATE_SETTINGS_PLUGIN_LOADER_C,
+ MATE_SETTINGS_PLUGIN_LOADER_PY
+} MateSettingsPluginLoader;
+
+struct MateSettingsPluginInfoPrivate
+{
+ char *file;
+ MateConfClient *client;
+
+ char *location;
+ MateSettingsPluginLoader loader;
+ GTypeModule *module;
+
+ char *name;
+ char *desc;
+ char **authors;
+ char *copyright;
+ char *website;
+
+ MateSettingsPlugin *plugin;
+
+ int enabled : 1;
+ int active : 1;
+
+ /* A plugin is unavailable if it is not possible to activate it
+ due to an error loading the plugin module (e.g. for Python plugins
+ when the interpreter has not been correctly initializated) */
+ int available : 1;
+
+ guint enabled_notification_id;
+
+ /* Priority determines the order in which plugins are started and
+ * stopped. A lower number means higher priority. */
+ guint priority;
+};
+
+
+enum {
+ ACTIVATED,
+ DEACTIVATED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (MateSettingsPluginInfo, mate_settings_plugin_info, G_TYPE_OBJECT)
+
+static void
+mate_settings_plugin_info_finalize (GObject *object)
+{
+ MateSettingsPluginInfo *info;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (object));
+
+ info = MATE_SETTINGS_PLUGIN_INFO (object);
+
+ g_return_if_fail (info->priv != NULL);
+
+ if (info->priv->plugin != NULL) {
+ g_debug ("Unref plugin %s", info->priv->name);
+
+ g_object_unref (info->priv->plugin);
+
+ /* info->priv->module must not be unref since it is not possible to finalize
+ * a type module */
+ }
+
+ g_free (info->priv->file);
+ g_free (info->priv->location);
+ g_free (info->priv->name);
+ g_free (info->priv->desc);
+ g_free (info->priv->website);
+ g_free (info->priv->copyright);
+ g_strfreev (info->priv->authors);
+
+ if (info->priv->enabled_notification_id != 0) {
+ mateconf_client_notify_remove (info->priv->client,
+ info->priv->enabled_notification_id);
+
+ info->priv->enabled_notification_id = 0;
+ }
+
+ g_object_unref (info->priv->client);
+
+ G_OBJECT_CLASS (mate_settings_plugin_info_parent_class)->finalize (object);
+}
+
+static void
+mate_settings_plugin_info_class_init (MateSettingsPluginInfoClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = mate_settings_plugin_info_finalize;
+
+ signals [ACTIVATED] =
+ g_signal_new ("activated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MateSettingsPluginInfoClass, activated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals [DEACTIVATED] =
+ g_signal_new ("deactivated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MateSettingsPluginInfoClass, deactivated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_type_class_add_private (klass, sizeof (MateSettingsPluginInfoPrivate));
+}
+
+static void
+mate_settings_plugin_info_init (MateSettingsPluginInfo *info)
+{
+ info->priv = MATE_SETTINGS_PLUGIN_INFO_GET_PRIVATE (info);
+ info->priv->client = mateconf_client_get_default ();
+}
+
+static void
+debug_info (MateSettingsPluginInfo *info)
+{
+ g_debug ("MateSettingsPluginInfo: name='%s' file='%s' location='%s'",
+ info->priv->name,
+ info->priv->file,
+ info->priv->location);
+}
+
+static gboolean
+mate_settings_plugin_info_fill_from_file (MateSettingsPluginInfo *info,
+ const char *filename)
+{
+ GKeyFile *plugin_file = NULL;
+ char *str;
+ int priority;
+ gboolean ret;
+
+ mate_settings_profile_start ("%s", filename);
+
+ ret = FALSE;
+
+ info->priv->file = g_strdup (filename);
+
+ plugin_file = g_key_file_new ();
+ if (! g_key_file_load_from_file (plugin_file, filename, G_KEY_FILE_NONE, NULL)) {
+ g_warning ("Bad plugin file: %s", filename);
+ goto out;
+ }
+
+ if (! g_key_file_has_key (plugin_file, PLUGIN_GROUP, "IAge", NULL)) {
+ g_debug ("IAge key does not exist in file: %s", filename);
+ goto out;
+ }
+
+ /* Check IAge=2 */
+ if (g_key_file_get_integer (plugin_file, PLUGIN_GROUP, "IAge", NULL) != 0) {
+ g_debug ("Wrong IAge in file: %s", filename);
+ goto out;
+ }
+
+ /* Get Location */
+ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Module", NULL);
+
+ if ((str != NULL) && (*str != '\0')) {
+ info->priv->location = str;
+ } else {
+ g_free (str);
+ g_warning ("Could not find 'Module' in %s", filename);
+ goto out;
+ }
+
+ /* Get the loader for this plugin */
+ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Loader", NULL);
+ if (str != NULL && strcmp (str, "python") == 0) {
+ info->priv->loader = MATE_SETTINGS_PLUGIN_LOADER_PY;
+#ifndef ENABLE_PYTHON
+ g_warning ("Cannot load Python plugin '%s' since mate_settings was not "
+ "compiled with Python support.", filename);
+ goto out;
+#endif
+ } else {
+ info->priv->loader = MATE_SETTINGS_PLUGIN_LOADER_C;
+ }
+ g_free (str);
+
+ /* Get Name */
+ str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Name", NULL, NULL);
+ if (str != NULL) {
+ info->priv->name = str;
+ } else {
+ g_warning ("Could not find 'Name' in %s", filename);
+ goto out;
+ }
+
+ /* Get Description */
+ str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Description", NULL, NULL);
+ if (str != NULL) {
+ info->priv->desc = str;
+ } else {
+ g_debug ("Could not find 'Description' in %s", filename);
+ }
+
+ /* Get Authors */
+ info->priv->authors = g_key_file_get_string_list (plugin_file, PLUGIN_GROUP, "Authors", NULL, NULL);
+ if (info->priv->authors == NULL) {
+ g_debug ("Could not find 'Authors' in %s", filename);
+ }
+
+ /* Get Copyright */
+ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Copyright", NULL);
+ if (str != NULL) {
+ info->priv->copyright = str;
+ } else {
+ g_debug ("Could not find 'Copyright' in %s", filename);
+ }
+
+ /* Get Website */
+ str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Website", NULL);
+ if (str != NULL) {
+ info->priv->website = str;
+ } else {
+ g_debug ("Could not find 'Website' in %s", filename);
+ }
+
+ /* Get Priority */
+ priority = g_key_file_get_integer (plugin_file, PLUGIN_GROUP, "Priority", NULL);
+ if (priority >= PLUGIN_PRIORITY_MAX) {
+ info->priv->priority = priority;
+ } else {
+ info->priv->priority = PLUGIN_PRIORITY_DEFAULT;
+ }
+
+ g_key_file_free (plugin_file);
+
+ debug_info (info);
+
+ /* If we know nothing about the availability of the plugin,
+ set it as available */
+ info->priv->available = TRUE;
+
+ ret = TRUE;
+ out:
+ mate_settings_profile_end ("%s", filename);
+
+ return ret;
+}
+
+static void
+plugin_enabled_cb (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ MateSettingsPluginInfo *info)
+{
+ if (mateconf_value_get_bool (entry->value)) {
+ mate_settings_plugin_info_activate (info);
+ } else {
+ mate_settings_plugin_info_deactivate (info);
+ }
+}
+
+void
+mate_settings_plugin_info_set_enabled_key_name (MateSettingsPluginInfo *info,
+ const char *key_name)
+{
+ info->priv->enabled_notification_id = mateconf_client_notify_add (info->priv->client,
+ key_name,
+ (MateConfClientNotifyFunc)plugin_enabled_cb,
+ info,
+ NULL,
+ NULL);
+
+ info->priv->enabled = mateconf_client_get_bool (info->priv->client, key_name, NULL);
+}
+
+MateSettingsPluginInfo *
+mate_settings_plugin_info_new_from_file (const char *filename)
+{
+ MateSettingsPluginInfo *info;
+ gboolean res;
+
+ info = g_object_new (MATE_TYPE_SETTINGS_PLUGIN_INFO, NULL);
+
+ res = mate_settings_plugin_info_fill_from_file (info, filename);
+ if (! res) {
+ g_object_unref (info);
+ info = NULL;
+ }
+
+ return info;
+}
+
+static void
+_deactivate_plugin (MateSettingsPluginInfo *info)
+{
+ mate_settings_plugin_deactivate (info->priv->plugin);
+ g_signal_emit (info, signals [DEACTIVATED], 0);
+}
+
+gboolean
+mate_settings_plugin_info_deactivate (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+
+ if (!info->priv->active || !info->priv->available) {
+ return TRUE;
+ }
+
+ _deactivate_plugin (info);
+
+ /* Update plugin state */
+ info->priv->active = FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+load_plugin_module (MateSettingsPluginInfo *info)
+{
+ char *path;
+ char *dirname;
+ gboolean ret;
+
+ ret = FALSE;
+
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+ g_return_val_if_fail (info->priv->file != NULL, FALSE);
+ g_return_val_if_fail (info->priv->location != NULL, FALSE);
+ g_return_val_if_fail (info->priv->plugin == NULL, FALSE);
+ g_return_val_if_fail (info->priv->available, FALSE);
+
+ mate_settings_profile_start ("%s", info->priv->location);
+
+ switch (info->priv->loader) {
+ case MATE_SETTINGS_PLUGIN_LOADER_C:
+ dirname = g_path_get_dirname (info->priv->file);
+ g_return_val_if_fail (dirname != NULL, FALSE);
+
+ path = g_module_build_path (dirname, info->priv->location);
+ g_free (dirname);
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ info->priv->module = G_TYPE_MODULE (mate_settings_module_new (path));
+ g_free (path);
+
+ break;
+
+#ifdef ENABLE_PYTHON
+ case MATE_SETTINGS_PLUGIN_LOADER_PY:
+ {
+ char *dir;
+
+ if (!mate_settings_python_init ()) {
+ /* Mark plugin as unavailable and fails */
+ info->priv->available = FALSE;
+
+ g_warning ("Cannot load Python plugin '%s' since mate_settings "
+ "was not able to initialize the Python interpreter.",
+ info->priv->name);
+
+ goto out;
+ }
+
+ dir = g_path_get_dirname (info->priv->file);
+
+ g_return_val_if_fail ((info->priv->location != NULL) &&
+ (info->priv->location[0] != '\0'),
+ FALSE);
+
+ info->priv->module = G_TYPE_MODULE (
+ mate_settings_python_module_new (dir, info->priv->location));
+
+ g_free (dir);
+ break;
+ }
+#endif
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+
+ if (!g_type_module_use (info->priv->module)) {
+ switch (info->priv->loader) {
+ case MATE_SETTINGS_PLUGIN_LOADER_C:
+ g_warning ("Cannot load plugin '%s' since file '%s' cannot be read.",
+ info->priv->name,
+ mate_settings_module_get_path (MATE_SETTINGS_MODULE (info->priv->module)));
+ break;
+
+ case MATE_SETTINGS_PLUGIN_LOADER_PY:
+ g_warning ("Cannot load Python plugin '%s' since file '%s' cannot be read.",
+ info->priv->name,
+ info->priv->location);
+ break;
+
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+
+ g_object_unref (G_OBJECT (info->priv->module));
+ info->priv->module = NULL;
+
+ /* Mark plugin as unavailable and fails */
+ info->priv->available = FALSE;
+
+ goto out;
+ }
+
+ switch (info->priv->loader) {
+ case MATE_SETTINGS_PLUGIN_LOADER_C:
+ info->priv->plugin =
+ MATE_SETTINGS_PLUGIN (mate_settings_module_new_object (MATE_SETTINGS_MODULE (info->priv->module)));
+ break;
+
+#ifdef ENABLE_PYTHON
+ case MATE_SETTINGS_PLUGIN_LOADER_PY:
+ info->priv->plugin =
+ MATE_SETTINGS_PLUGIN (mate_settings_python_module_new_object (MATE_SETTINGS_PYTHON_MODULE (info->priv->module)));
+ break;
+#endif
+
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+
+ g_type_module_unuse (info->priv->module);
+ ret = TRUE;
+ out:
+ mate_settings_profile_end ("%s", info->priv->location);
+ return ret;
+}
+
+static gboolean
+_activate_plugin (MateSettingsPluginInfo *info)
+{
+ gboolean res = TRUE;
+
+ if (!info->priv->available) {
+ /* Plugin is not available, don't try to activate/load it */
+ return FALSE;
+ }
+
+ if (info->priv->plugin == NULL) {
+ res = load_plugin_module (info);
+ }
+
+ if (res) {
+ mate_settings_plugin_activate (info->priv->plugin);
+ g_signal_emit (info, signals [ACTIVATED], 0);
+ } else {
+ g_warning ("Error activating plugin '%s'", info->priv->name);
+ }
+
+ return res;
+}
+
+gboolean
+mate_settings_plugin_info_activate (MateSettingsPluginInfo *info)
+{
+
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+
+ if (! info->priv->available) {
+ return FALSE;
+ }
+
+ if (info->priv->active) {
+ return TRUE;
+ }
+
+ if (_activate_plugin (info)) {
+ info->priv->active = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+mate_settings_plugin_info_is_active (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+
+ return (info->priv->available && info->priv->active);
+}
+
+gboolean
+mate_settings_plugin_info_get_enabled (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+
+ return (info->priv->enabled);
+}
+
+gboolean
+mate_settings_plugin_info_is_available (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), FALSE);
+
+ return (info->priv->available != FALSE);
+}
+
+const char *
+mate_settings_plugin_info_get_name (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), NULL);
+
+ return info->priv->name;
+}
+
+const char *
+mate_settings_plugin_info_get_description (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), NULL);
+
+ return info->priv->desc;
+}
+
+const char **
+mate_settings_plugin_info_get_authors (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), (const char **)NULL);
+
+ return (const char **)info->priv->authors;
+}
+
+const char *
+mate_settings_plugin_info_get_website (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), NULL);
+
+ return info->priv->website;
+}
+
+const char *
+mate_settings_plugin_info_get_copyright (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), NULL);
+
+ return info->priv->copyright;
+}
+
+
+const char *
+mate_settings_plugin_info_get_location (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), NULL);
+
+ return info->priv->location;
+}
+
+int
+mate_settings_plugin_info_get_priority (MateSettingsPluginInfo *info)
+{
+ g_return_val_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info), PLUGIN_PRIORITY_DEFAULT);
+
+ return info->priv->priority;
+}
+
+void
+mate_settings_plugin_info_set_priority (MateSettingsPluginInfo *info,
+ int priority)
+{
+ g_return_if_fail (MATE_IS_SETTINGS_PLUGIN_INFO (info));
+
+ info->priv->priority = priority;
+}