1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2002-2005 Paolo Maggi
4
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330,
19
* Boston, MA 02111-1307, USA.
27
#include <glib/gi18n.h>
29
#include <gconf/gconf-client.h>
31
#include "gnome-settings-plugins-engine.h"
32
#include "gnome-settings-plugin.h"
34
#include "gnome-settings-module.h"
36
#define PLUGIN_EXT ".gnome-settings-plugin"
37
#define PLUGIN_GROUP "GNOME Settings Plugin"
41
GNOME_SETTINGS_PLUGIN_LOADER_C,
42
GNOME_SETTINGS_PLUGIN_LOADER_PY,
43
} GnomeSettingsPluginLoader;
45
struct _GnomeSettingsPluginInfo
50
GnomeSettingsPluginLoader loader;
59
GnomeSettingsPlugin *plugin;
63
guint active_notification_id;
65
/* A plugin is unavailable if it is not possible to activate it
66
due to an error loading the plugin module (e.g. for Python plugins
67
when the interpreter has not been correctly initializated) */
71
static char *gnome_settings_gconf_prefix = NULL;
72
static GHashTable *gnome_settings_plugins = NULL;
73
static GConfClient *client = NULL;
76
gnome_settings_plugin_info_free (GnomeSettingsPluginInfo *info)
78
if (info->plugin != NULL) {
79
g_debug ("Unref plugin %s", info->name);
81
g_object_unref (info->plugin);
83
/* info->module must not be unref since it is not possible to finalize
88
g_free (info->location);
91
g_free (info->website);
92
g_free (info->copyright);
93
g_strfreev (info->authors);
98
static GnomeSettingsPluginInfo *
99
gnome_settings_plugins_engine_load (const char *file)
101
GnomeSettingsPluginInfo *info;
102
GKeyFile *plugin_file = NULL;
105
g_return_val_if_fail (file != NULL, NULL);
107
g_debug ("Loading plugin: %s", file);
109
info = g_new0 (GnomeSettingsPluginInfo, 1);
110
info->file = g_strdup (file);
112
plugin_file = g_key_file_new ();
113
if (! g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL)) {
114
g_warning ("Bad plugin file: %s", file);
118
if (! g_key_file_has_key (plugin_file, PLUGIN_GROUP, "IAge", NULL)) {
119
g_debug ("IAge key does not exist in file: %s", file);
124
if (g_key_file_get_integer (plugin_file, PLUGIN_GROUP, "IAge", NULL) != 0) {
125
g_debug ("Wrong IAge in file: %s", file);
130
str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Module", NULL);
132
if ((str != NULL) && (*str != '\0')) {
133
info->location = str;
135
g_warning ("Could not find 'Module' in %s", file);
139
/* Get the loader for this plugin */
140
str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Loader", NULL);
141
if (str && strcmp(str, "python") == 0) {
142
info->loader = GNOME_SETTINGS_PLUGIN_LOADER_PY;
143
#ifndef ENABLE_PYTHON
144
g_warning ("Cannot load Python plugin '%s' since gnome_settings was not "
145
"compiled with Python support.", file);
149
info->loader = GNOME_SETTINGS_PLUGIN_LOADER_C;
154
str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Name", NULL, NULL);
158
g_warning ("Could not find 'Name' in %s", file);
162
/* Get Description */
163
str = g_key_file_get_locale_string (plugin_file, PLUGIN_GROUP, "Description", NULL, NULL);
167
g_debug ("Could not find 'Description' in %s", file);
170
info->authors = g_key_file_get_string_list (plugin_file, PLUGIN_GROUP, "Authors", NULL, NULL);
171
if (info->authors == NULL)
172
g_debug ("Could not find 'Authors' in %s", file);
175
str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Copyright", NULL);
177
info->copyright = str;
179
g_debug ("Could not find 'Copyright' in %s", file);
182
str = g_key_file_get_string (plugin_file, PLUGIN_GROUP, "Website", NULL);
186
g_debug ("Could not find 'Website' in %s", file);
188
g_key_file_free (plugin_file);
190
/* If we know nothing about the availability of the plugin,
191
set it as available */
192
info->available = TRUE;
198
g_free (info->location);
201
g_key_file_free (plugin_file);
207
gnome_settings_plugins_engine_plugin_active_cb (GConfClient *client,
210
GnomeSettingsPluginInfo *info)
212
if (gconf_value_get_bool (entry->value)) {
213
gnome_settings_plugins_engine_activate_plugin (info);
215
gnome_settings_plugins_engine_deactivate_plugin (info);
220
gnome_settings_plugins_engine_load_file (const char *filename)
222
GnomeSettingsPluginInfo *info;
226
if (g_str_has_suffix (filename, PLUGIN_EXT) == FALSE) {
230
info = gnome_settings_plugins_engine_load (filename);
235
if (g_hash_table_lookup (gnome_settings_plugins, info->location)) {
236
gnome_settings_plugin_info_free (info);
240
g_hash_table_insert (gnome_settings_plugins, info->location, info);
242
key_name = g_strdup_printf ("%s/%s", gnome_settings_gconf_prefix, info->location);
243
gconf_client_add_dir (client, key_name, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
246
key_name = g_strdup_printf ("%s/%s/active", gnome_settings_gconf_prefix, info->location);
248
info->active_notification_id = gconf_client_notify_add (client,
250
(GConfClientNotifyFunc)gnome_settings_plugins_engine_plugin_active_cb,
255
g_debug ("Reading gconf key: %s", key_name);
256
activate = gconf_client_get_bool (client, key_name, NULL);
261
res = gnome_settings_plugins_engine_activate_plugin (info);
263
g_debug ("Plugin %s: active", info->location);
265
g_debug ("Plugin %s: activation failed", info->location);
268
g_debug ("Plugin %s: inactive", info->location);
273
gnome_settings_plugins_engine_load_dir (const char *path)
279
g_debug ("Loading settings plugins from dir: %s", path);
282
d = g_dir_open (path, 0, &error);
284
g_warning (error->message);
285
g_error_free (error);
289
while ((name = g_dir_read_name (d))) {
292
filename = g_build_filename (path, name, NULL);
293
if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE) {
294
gnome_settings_plugins_engine_load_dir (filename);
296
gnome_settings_plugins_engine_load_file (filename);
306
gnome_settings_plugins_engine_load_all (void)
308
/* load system plugins */
309
gnome_settings_plugins_engine_load_dir (GNOME_SETTINGS_PLUGINDIR "/");
313
gnome_settings_plugins_engine_init (const char *gconf_prefix)
315
g_return_val_if_fail (gnome_settings_plugins == NULL, FALSE);
316
g_return_val_if_fail (gconf_prefix != NULL, FALSE);
318
if (!g_module_supported ()) {
319
g_warning ("gnome_settings is not able to initialize the plugins engine.");
323
gnome_settings_plugins = g_hash_table_new_full (g_str_hash,
326
(GDestroyNotify)gnome_settings_plugin_info_free);
328
gnome_settings_gconf_prefix = g_strdup (gconf_prefix);
330
client = gconf_client_get_default ();
332
gnome_settings_plugins_engine_load_all ();
338
gnome_settings_plugins_engine_garbage_collect (void)
341
gnome_settings_python_garbage_collect ();
346
gnome_settings_plugins_engine_shutdown (void)
350
/* Note: that this may cause finalization of objects by
351
* running the garbage collector. Since some of the plugin may
352
* have installed callbacks upon object finalization it must
353
* run before we get rid of the plugins.
355
gnome_settings_python_shutdown ();
358
if (gnome_settings_plugins != NULL) {
359
g_hash_table_destroy (gnome_settings_plugins);
360
gnome_settings_plugins = NULL;
363
if (client != NULL) {
364
g_object_unref (client);
368
g_free (gnome_settings_gconf_prefix);
369
gnome_settings_gconf_prefix = NULL;
373
collate_values_cb (gpointer key,
377
*list = g_list_prepend (*list, value);
381
gnome_settings_plugins_engine_get_plugins_list (void)
385
if (gnome_settings_plugins == NULL) {
389
g_hash_table_foreach (gnome_settings_plugins, (GHFunc)collate_values_cb, &list);
390
list = g_list_reverse (list);
396
load_plugin_module (GnomeSettingsPluginInfo *info)
401
g_return_val_if_fail (info != NULL, FALSE);
402
g_return_val_if_fail (info->file != NULL, FALSE);
403
g_return_val_if_fail (info->location != NULL, FALSE);
404
g_return_val_if_fail (info->plugin == NULL, FALSE);
405
g_return_val_if_fail (info->available, FALSE);
407
switch (info->loader) {
408
case GNOME_SETTINGS_PLUGIN_LOADER_C:
409
dirname = g_path_get_dirname (info->file);
410
g_return_val_if_fail (dirname != NULL, FALSE);
412
path = g_module_build_path (dirname, info->location);
414
g_return_val_if_fail (path != NULL, FALSE);
416
info->module = G_TYPE_MODULE (gnome_settings_module_new (path));
422
case GNOME_SETTINGS_PLUGIN_LOADER_PY:
426
if (!gnome_settings_python_init ()) {
427
/* Mark plugin as unavailable and fails */
428
info->available = FALSE;
430
g_warning ("Cannot load Python plugin '%s' since gnome_settings "
431
"was not able to initialize the Python interpreter.",
437
dir = g_path_get_dirname (info->file);
439
g_return_val_if_fail ((info->location != NULL) &&
440
(info->location[0] != '\0'),
443
info->module = G_TYPE_MODULE (
444
gnome_settings_python_module_new (dir, info->location));
451
g_return_val_if_reached (FALSE);
454
if (!g_type_module_use (info->module)) {
455
switch (info->loader) {
456
case GNOME_SETTINGS_PLUGIN_LOADER_C:
457
g_warning ("Cannot load plugin '%s' since file '%s' cannot be read.",
459
gnome_settings_module_get_path (GNOME_SETTINGS_MODULE (info->module)));
462
case GNOME_SETTINGS_PLUGIN_LOADER_PY:
463
g_warning ("Cannot load Python plugin '%s' since file '%s' cannot be read.",
469
g_return_val_if_reached (FALSE);
472
g_object_unref (G_OBJECT (info->module));
475
/* Mark plugin as unavailable and fails */
476
info->available = FALSE;
481
switch (info->loader) {
482
case GNOME_SETTINGS_PLUGIN_LOADER_C:
484
GNOME_SETTINGS_PLUGIN (gnome_settings_module_new_object (GNOME_SETTINGS_MODULE (info->module)));
488
case GNOME_SETTINGS_PLUGIN_LOADER_PY:
490
GNOME_SETTINGS_PLUGIN (gnome_settings_python_module_new_object (GNOME_SETTINGS_PYTHON_MODULE (info->module)));
495
g_return_val_if_reached (FALSE);
498
g_type_module_unuse (info->module);
504
gnome_settings_plugins_engine_activate_plugin_real (GnomeSettingsPluginInfo *info)
508
if (!info->available) {
509
/* Plugin is not available, don't try to activate/load it */
513
if (info->plugin == NULL)
514
res = load_plugin_module (info);
517
gnome_settings_plugin_activate (info->plugin);
519
g_warning ("Error activating plugin '%s'", info->name);
526
gnome_settings_plugins_engine_activate_plugin (GnomeSettingsPluginInfo *info)
529
g_return_val_if_fail (info != NULL, FALSE);
531
if (! info->available) {
539
if (gnome_settings_plugins_engine_activate_plugin_real (info)) {
542
key_name = g_strdup_printf ("/%s/%s/active",
543
gnome_settings_gconf_prefix,
545
gconf_client_set_bool (client, key_name, TRUE, NULL);
557
gnome_settings_plugins_engine_deactivate_plugin_real (GnomeSettingsPluginInfo *info)
559
gnome_settings_plugin_deactivate (info->plugin);
563
gnome_settings_plugins_engine_deactivate_plugin (GnomeSettingsPluginInfo *info)
567
g_return_val_if_fail (info != NULL, FALSE);
569
if (!info->active || !info->available) {
573
gnome_settings_plugins_engine_deactivate_plugin_real (info);
575
/* Update plugin state */
576
info->active = FALSE;
578
key_name = g_strdup_printf ("/%s/%s/active",
579
gnome_settings_gconf_prefix,
581
gconf_client_set_bool (client, key_name, FALSE, NULL);
588
gnome_settings_plugins_engine_plugin_is_active (GnomeSettingsPluginInfo *info)
590
g_return_val_if_fail (info != NULL, FALSE);
592
return (info->available && info->active);
596
gnome_settings_plugins_engine_plugin_is_available (GnomeSettingsPluginInfo *info)
598
g_return_val_if_fail (info != NULL, FALSE);
600
return (info->available != FALSE);
604
gnome_settings_plugins_engine_get_plugin_name (GnomeSettingsPluginInfo *info)
606
g_return_val_if_fail (info != NULL, NULL);
612
gnome_settings_plugins_engine_get_plugin_description (GnomeSettingsPluginInfo *info)
614
g_return_val_if_fail (info != NULL, NULL);
620
gnome_settings_plugins_engine_get_plugin_authors (GnomeSettingsPluginInfo *info)
622
g_return_val_if_fail (info != NULL, (const char **)NULL);
624
return (const char **)info->authors;
628
gnome_settings_plugins_engine_get_plugin_website (GnomeSettingsPluginInfo *info)
630
g_return_val_if_fail (info != NULL, NULL);
632
return info->website;
636
gnome_settings_plugins_engine_get_plugin_copyright (GnomeSettingsPluginInfo *info)
638
g_return_val_if_fail (info != NULL, NULL);
640
return info->copyright;