1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * nemo-module.h - Interface to nemo extensions
4 *
5 * Copyright (C) 2003 Novell, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA.
20 *
21 * Author: Dave Camp <dave@ximian.com>
22 *
23 */
24
25 #include <config.h>
26 #include "nemo-module.h"
27 #include <libnemo-private/nemo-global-preferences.h>
28
29 #include <eel/eel-debug.h>
30
31 static GList *module_objects = NULL;
32
33 G_DEFINE_TYPE (NemoModule, nemo_module, G_TYPE_TYPE_MODULE);
34
35 static gboolean
nemo_module_load(GTypeModule * gmodule)36 nemo_module_load (GTypeModule *gmodule)
37 {
38 NemoModule *module;
39
40 module = NEMO_MODULE (gmodule);
41
42 module->library = g_module_open (module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
43
44 if (!module->library) {
45 g_warning ("%s", g_module_error ());
46 return FALSE;
47 }
48
49 if (!g_module_symbol (module->library,
50 "nemo_module_initialize",
51 (gpointer *)&module->initialize) ||
52 !g_module_symbol (module->library,
53 "nemo_module_shutdown",
54 (gpointer *)&module->shutdown) ||
55 !g_module_symbol (module->library,
56 "nemo_module_list_types",
57 (gpointer *)&module->list_types)) {
58
59 g_warning ("%s", g_module_error ());
60 g_module_close (module->library);
61
62 return FALSE;
63 }
64
65 module->initialize (gmodule);
66
67 return TRUE;
68 }
69
70 static void
nemo_module_unload(GTypeModule * gmodule)71 nemo_module_unload (GTypeModule *gmodule)
72 {
73 NemoModule *module;
74
75 module = NEMO_MODULE (gmodule);
76
77 module->shutdown ();
78
79 g_module_close (module->library);
80
81 module->initialize = NULL;
82 module->shutdown = NULL;
83 module->list_types = NULL;
84 }
85
86 static void
nemo_module_finalize(GObject * object)87 nemo_module_finalize (GObject *object)
88 {
89 NemoModule *module;
90
91 module = NEMO_MODULE (object);
92
93 g_free (module->path);
94
95 G_OBJECT_CLASS (nemo_module_parent_class)->finalize (object);
96 }
97
98 static void
nemo_module_init(NemoModule * module)99 nemo_module_init (NemoModule *module)
100 {
101 }
102
103 static void
nemo_module_class_init(NemoModuleClass * class)104 nemo_module_class_init (NemoModuleClass *class)
105 {
106 G_OBJECT_CLASS (class)->finalize = nemo_module_finalize;
107 G_TYPE_MODULE_CLASS (class)->load = nemo_module_load;
108 G_TYPE_MODULE_CLASS (class)->unload = nemo_module_unload;
109 }
110
111 static void
module_object_weak_notify(gpointer user_data,GObject * object)112 module_object_weak_notify (gpointer user_data, GObject *object)
113 {
114 module_objects = g_list_remove (module_objects, object);
115 }
116
117 static gboolean
module_is_selected(GType type)118 module_is_selected (GType type)
119 {
120 gchar **disabled_list = g_settings_get_strv (nemo_plugin_preferences, NEMO_PLUGIN_PREFERENCES_DISABLED_EXTENSIONS);
121
122 gboolean ret = TRUE;
123 guint i = 0;
124
125 for (i = 0; i < g_strv_length (disabled_list); i++) {
126 if (g_strcmp0 (disabled_list[i], g_type_name (type)) == 0)
127 ret = FALSE;
128 }
129
130 g_strfreev (disabled_list);
131 return ret;
132 }
133
134 static void
add_module_objects(NemoModule * module)135 add_module_objects (NemoModule *module)
136 {
137 const GType *types;
138 int num_types;
139 int i;
140
141 module->list_types (&types, &num_types);
142
143 for (i = 0; i < num_types; i++) {
144 if (types[i] == 0) { /* Work around broken extensions */
145 break;
146 }
147 if (module_is_selected (types[i])) {
148 nemo_module_add_type (types[i]);
149 }
150 }
151 }
152
153 static void
nemo_module_load_file(const char * filename)154 nemo_module_load_file (const char *filename)
155 {
156 NemoModule *module = NULL;
157
158 module = g_object_new (NEMO_TYPE_MODULE, NULL);
159 module->path = g_strdup (filename);
160
161 if (g_type_module_use (G_TYPE_MODULE (module))) {
162 add_module_objects (module);
163 g_type_module_unuse (G_TYPE_MODULE (module));
164 } else {
165 g_object_unref (module);
166 }
167 }
168
169 static void
load_module_dir(const char * dirname)170 load_module_dir (const char *dirname)
171 {
172 GDir *dir;
173
174 dir = g_dir_open (dirname, 0, NULL);
175
176 if (dir) {
177 const char *name;
178
179 while ((name = g_dir_read_name (dir))) {
180 if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) {
181 char *filename;
182
183 filename = g_build_filename (dirname,
184 name,
185 NULL);
186 nemo_module_load_file (filename);
187 g_free (filename);
188 }
189 }
190
191 g_dir_close (dir);
192 }
193 }
194
195 static void
free_module_objects(void)196 free_module_objects (void)
197 {
198 GList *l, *next;
199
200 for (l = module_objects; l != NULL; l = next) {
201 next = l->next;
202 g_object_unref (l->data);
203 }
204
205 g_list_free (module_objects);
206 }
207
208 void
nemo_module_setup(void)209 nemo_module_setup (void)
210 {
211 static gboolean initialized = FALSE;
212
213 if (!initialized) {
214 initialized = TRUE;
215
216 load_module_dir (NEMO_EXTENSIONDIR);
217
218 eel_debug_call_at_shutdown (free_module_objects);
219 }
220 }
221
222 GList *
nemo_module_get_extensions_for_type(GType type)223 nemo_module_get_extensions_for_type (GType type)
224 {
225 GList *l;
226 GList *ret = NULL;
227
228 for (l = module_objects; l != NULL; l = l->next) {
229 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data),
230 type)) {
231 g_object_ref (l->data);
232 ret = g_list_prepend (ret, l->data);
233 }
234 }
235
236 return ret;
237 }
238
239 void
nemo_module_extension_list_free(GList * extensions)240 nemo_module_extension_list_free (GList *extensions)
241 {
242 GList *l, *next;
243
244 for (l = extensions; l != NULL; l = next) {
245 next = l->next;
246 g_object_unref (l->data);
247 }
248 g_list_free (extensions);
249 }
250
251 void
nemo_module_add_type(GType type)252 nemo_module_add_type (GType type)
253 {
254 GObject *object;
255
256 object = g_object_new (type, NULL);
257 g_object_weak_ref (object,
258 (GWeakNotify)module_object_weak_notify,
259 NULL);
260
261 module_objects = g_list_prepend (module_objects, object);
262 }
263