1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program 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
15 * 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <glib/gstdio.h>
23 #include <dlfcn.h>
24
25 #include "gldi-config.h"
26 #include "gldi-module-config.h"
27 #include "cairo-dock-dock-manager.h"
28 #include "cairo-dock-themes-manager.h" // cairo_dock_add_conf_file
29 #include "cairo-dock-file-manager.h" // cairo_dock_copy_file
30 #include "cairo-dock-log.h"
31 #include "cairo-dock-applet-manager.h"
32 #include "cairo-dock-desktop-manager.h" // gldi_desktop_get_width
33 #include "cairo-dock-desklet-manager.h"
34 #include "cairo-dock-animations.h"
35 #include "cairo-dock-config.h"
36 #include "cairo-dock-module-instance-manager.h"
37 #define _MANAGER_DEF_
38 #include "cairo-dock-module-manager.h"
39
40 // public (manager, config, data)
41 GldiModulesParam myModulesParam;
42 GldiManager myModulesMgr;
43 GldiObjectManager myModuleObjectMgr;
44
45 GldiModuleInstance *g_pCurrentModule = NULL; // only used to trace a possible crash in one of the modules.
46
47 // dependancies
48 extern gchar *g_cConfFile;
49 extern gchar *g_cCurrentThemePath;
50 extern int g_iMajorVersion, g_iMinorVersion, g_iMicroVersion;
51 extern gboolean g_bEasterEggs;
52
53 // private
54 static GHashTable *s_hModuleTable = NULL;
55 static GList *s_AutoLoadedModules = NULL;
56 static guint s_iSidWriteModules = 0;
57
58
59 ///////////////
60 /// MANAGER ///
61 ///////////////
62
gldi_module_get(const gchar * cModuleName)63 GldiModule *gldi_module_get (const gchar *cModuleName)
64 {
65 g_return_val_if_fail (cModuleName != NULL, NULL);
66 return g_hash_table_lookup (s_hModuleTable, cModuleName);
67 }
68
gldi_module_foreach(GHRFunc pCallback,gpointer user_data)69 GldiModule *gldi_module_foreach (GHRFunc pCallback, gpointer user_data)
70 {
71 return g_hash_table_find (s_hModuleTable, (GHRFunc) pCallback, user_data);
72 }
73
_sort_module_by_alphabetical_order(GldiModule * m1,GldiModule * m2)74 static int _sort_module_by_alphabetical_order (GldiModule *m1, GldiModule *m2)
75 {
76 if (!m1 || !m1->pVisitCard || !m1->pVisitCard->cTitle)
77 return 1;
78 if (!m2 || !m2->pVisitCard || !m2->pVisitCard->cTitle)
79 return -1;
80 return g_ascii_strncasecmp (m1->pVisitCard->cTitle, m2->pVisitCard->cTitle, -1);
81 }
gldi_module_foreach_in_alphabetical_order(GCompareFunc pCallback,gpointer user_data)82 GldiModule *gldi_module_foreach_in_alphabetical_order (GCompareFunc pCallback, gpointer user_data)
83 {
84 GList *pModuleList = g_hash_table_get_values (s_hModuleTable);
85 pModuleList = g_list_sort (pModuleList, (GCompareFunc) _sort_module_by_alphabetical_order);
86
87 GldiModule *pModule = (GldiModule *)g_list_find_custom (pModuleList, user_data, pCallback);
88
89 g_list_free (pModuleList);
90 return pModule;
91 }
92
gldi_module_get_nb(void)93 int gldi_module_get_nb (void)
94 {
95 return g_hash_table_size (s_hModuleTable);
96 }
97
_write_one_module_name(const gchar * cModuleName,GldiModule * pModule,GString * pString)98 static void _write_one_module_name (const gchar *cModuleName, GldiModule *pModule, GString *pString)
99 {
100 if (pModule->pInstancesList != NULL && ! gldi_module_is_auto_loaded (pModule))
101 {
102 g_string_append_printf (pString, "%s;", cModuleName);
103 }
104 }
_gldi_module_list_active(void)105 static gchar *_gldi_module_list_active (void)
106 {
107 GString *pString = g_string_new ("");
108
109 g_hash_table_foreach (s_hModuleTable, (GHFunc) _write_one_module_name, pString);
110
111 if (pString->len > 0)
112 pString->str[pString->len-1] = '\0';
113
114 gchar *cModuleNames = pString->str;
115 g_string_free (pString, FALSE);
116 return cModuleNames;
117 }
118
_write_modules_idle(G_GNUC_UNUSED gpointer data)119 static gboolean _write_modules_idle (G_GNUC_UNUSED gpointer data)
120 {
121 gchar *cModuleNames = _gldi_module_list_active ();
122 cd_debug ("%s", cModuleNames);
123 cairo_dock_update_conf_file (g_cConfFile,
124 G_TYPE_STRING, "System", "modules", cModuleNames,
125 G_TYPE_INVALID);
126 g_free (cModuleNames);
127 s_iSidWriteModules = 0;
128 return FALSE;
129 }
gldi_modules_write_active(void)130 void gldi_modules_write_active (void)
131 {
132 if (s_iSidWriteModules == 0)
133 s_iSidWriteModules = g_idle_add (_write_modules_idle, NULL);
134 }
135
136
137 /////////////////////
138 /// MODULE LOADER ///
139 /////////////////////
140
gldi_module_new(GldiVisitCard * pVisitCard,GldiModuleInterface * pInterface)141 GldiModule *gldi_module_new (GldiVisitCard *pVisitCard, GldiModuleInterface *pInterface)
142 {
143 g_return_val_if_fail (pVisitCard != NULL && pVisitCard->cModuleName != NULL, NULL);
144
145 GldiModuleAttr attr = {pVisitCard, pInterface};
146 return (GldiModule*)gldi_object_new (&myModuleObjectMgr, &attr);
147 }
148
gldi_module_new_from_so_file(const gchar * cSoFilePath)149 GldiModule *gldi_module_new_from_so_file (const gchar *cSoFilePath)
150 {
151 g_return_val_if_fail (cSoFilePath != NULL, NULL);
152 GldiVisitCard *pVisitCard = NULL;
153 GldiModuleInterface *pInterface = NULL;
154
155 // open the .so file
156 ///GModule *module = g_module_open (pGldiModule->cSoFilePath, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
157 gpointer handle = dlopen (cSoFilePath, RTLD_LAZY | RTLD_LOCAL);
158 if (! handle)
159 {
160 cd_warning ("while opening module '%s' : (%s)", cSoFilePath, dlerror());
161 return NULL;
162 }
163
164 // find the pre-init entry point
165 GldiModulePreInit function_pre_init = NULL;
166 /**bSymbolFound = g_module_symbol (module, "pre_init", (gpointer) &function_pre_init);
167 if (bSymbolFound && function_pre_init != NULL)*/
168 function_pre_init = dlsym (handle, "pre_init");
169 if (function_pre_init == NULL)
170 {
171 cd_warning ("this module ('%s') does not have the common entry point 'pre_init', it may be broken or icompatible with cairo-dock", cSoFilePath);
172 goto discard;
173 }
174
175 // run the pre-init entry point to get the necessary info about the module
176 pVisitCard = g_new0 (GldiVisitCard, 1);
177 pInterface = g_new0 (GldiModuleInterface, 1);
178 gboolean bModuleLoaded = function_pre_init (pVisitCard, pInterface);
179 if (! bModuleLoaded)
180 {
181 cd_debug ("module '%s' has not been loaded", cSoFilePath); // can happen to xxx-integration or icon-effect for instance.
182 goto discard;
183 }
184
185 // check module compatibility
186 if (! g_bEasterEggs &&
187 (pVisitCard->iMajorVersionNeeded > g_iMajorVersion
188 || (pVisitCard->iMajorVersionNeeded == g_iMajorVersion && pVisitCard->iMinorVersionNeeded > g_iMinorVersion)
189 || (pVisitCard->iMajorVersionNeeded == g_iMajorVersion && pVisitCard->iMinorVersionNeeded == g_iMinorVersion && pVisitCard->iMicroVersionNeeded > g_iMicroVersion)))
190 {
191 cd_warning ("this module ('%s') needs at least Cairo-Dock v%d.%d.%d, but Cairo-Dock is in v%d.%d.%d (%s)\n It will be ignored", cSoFilePath, pVisitCard->iMajorVersionNeeded, pVisitCard->iMinorVersionNeeded, pVisitCard->iMicroVersionNeeded, g_iMajorVersion, g_iMinorVersion, g_iMicroVersion, GLDI_VERSION);
192 goto discard;
193 }
194 if (! g_bEasterEggs
195 && pVisitCard->cDockVersionOnCompilation != NULL && strcmp (pVisitCard->cDockVersionOnCompilation, GLDI_VERSION) != 0) // separation des versions en easter egg.
196 {
197 cd_warning ("this module ('%s') was compiled with Cairo-Dock v%s, but Cairo-Dock is in v%s\n It will be ignored", cSoFilePath, pVisitCard->cDockVersionOnCompilation, GLDI_VERSION);
198 goto discard;
199 }
200
201 // create a new module with these info
202 GldiModule *pModule = gldi_module_new (pVisitCard, pInterface); // takes ownership of pVisitCard and pInterface
203 if (pModule)
204 pModule->handle = handle;
205 return pModule;
206
207 discard:
208 ///g_module_close (pModule);
209 dlclose (handle);
210 cairo_dock_free_visit_card (pVisitCard);
211 g_free (pInterface);
212 return NULL;
213 }
214
gldi_modules_new_from_directory(const gchar * cModuleDirPath,GError ** erreur)215 void gldi_modules_new_from_directory (const gchar *cModuleDirPath, GError **erreur)
216 {
217 if (cModuleDirPath == NULL)
218 cModuleDirPath = GLDI_MODULES_DIR;
219 cd_message ("%s (%s)", __func__, cModuleDirPath);
220
221 GError *tmp_erreur = NULL;
222 GDir *dir = g_dir_open (cModuleDirPath, 0, &tmp_erreur);
223 if (tmp_erreur != NULL)
224 {
225 g_propagate_error (erreur, tmp_erreur);
226 return ;
227 }
228
229 const gchar *cFileName;
230 GString *sFilePath = g_string_new ("");
231 do
232 {
233 cFileName = g_dir_read_name (dir);
234 if (cFileName == NULL)
235 break ;
236
237 if (g_str_has_suffix (cFileName, ".so"))
238 {
239 g_string_printf (sFilePath, "%s/%s", cModuleDirPath, cFileName);
240 (void)gldi_module_new_from_so_file (sFilePath->str);
241 }
242 }
243 while (1);
244 g_string_free (sFilePath, TRUE);
245 g_dir_close (dir);
246 }
247
gldi_module_get_config_dir(GldiModule * pModule)248 gchar *gldi_module_get_config_dir (GldiModule *pModule)
249 {
250 GldiVisitCard *pVisitCard = pModule->pVisitCard;
251 if (pVisitCard->cConfFileName == NULL)
252 return NULL;
253
254 gchar *cUserDataDirPath = g_strdup_printf ("%s/plug-ins/%s", g_cCurrentThemePath, pVisitCard->cUserDataDir);
255 if (! g_file_test (cUserDataDirPath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
256 {
257 cd_message ("directory %s doesn't exist, it will be added.", cUserDataDirPath);
258
259 gchar *command = g_strdup_printf ("mkdir -p \"%s\"", cUserDataDirPath);
260 int r = system (command);
261 g_free (command);
262
263 if (r != 0)
264 {
265 cd_warning ("couldn't create a directory for applet '%s' in '%s/plug-ins'\n check writing permissions", pVisitCard->cModuleName, g_cCurrentThemePath);
266 g_free (cUserDataDirPath);
267 g_free (pModule->cConfFilePath);
268 pModule->cConfFilePath = NULL;
269 return NULL;
270 }
271 }
272
273 return cUserDataDirPath;
274 }
275
cairo_dock_free_visit_card(GldiVisitCard * pVisitCard)276 void cairo_dock_free_visit_card (GldiVisitCard *pVisitCard)
277 {
278 g_free (pVisitCard); // toutes les chaines sont statiques.
279 }
280
281
282 /////////////////////////
283 /// MODULES HIGH LEVEL///
284 /////////////////////////
285
gldi_module_activate(GldiModule * module)286 void gldi_module_activate (GldiModule *module)
287 {
288 g_return_if_fail (module != NULL && module->pVisitCard != NULL);
289 cd_debug ("%s (%s)", __func__, module->pVisitCard->cModuleName);
290
291 if (module->pInstancesList != NULL)
292 {
293 cd_warning ("Module %s already active", module->pVisitCard->cModuleName);
294 return ;
295 }
296
297 if (module->pVisitCard->cConfFileName != NULL) // the module has a conf file -> create an instance for each of them.
298 {
299 // check that the module's config dir exists or create it.
300 gchar *cUserDataDirPath = gldi_module_get_config_dir (module);
301 if (cUserDataDirPath == NULL)
302 {
303 cd_warning ("Unable to open the config folder of module %s\nCheck permissions", module->pVisitCard->cModuleName);
304 return;
305 }
306
307 // look for conf files inside this folder, and create an instance for each of them.
308 int n = 0;
309 if (module->pVisitCard->bMultiInstance) // possibly several conf files.
310 {
311 // open it
312 GError *tmp_erreur = NULL;
313 GDir *dir = g_dir_open (cUserDataDirPath, 0, &tmp_erreur);
314 if (tmp_erreur != NULL)
315 {
316 cd_warning ("couldn't open folder %s (%s)", cUserDataDirPath, tmp_erreur->message);
317 g_error_free (tmp_erreur);
318 g_free (cUserDataDirPath);
319 return ;
320 }
321
322 // for each conf file inside, instanciate the module with it.
323 const gchar *cFileName;
324 gchar *cInstanceFilePath;
325
326 while ((cFileName = g_dir_read_name (dir)) != NULL)
327 {
328 gchar *str = strstr (cFileName, ".conf");
329 if (!str)
330 continue;
331 if (*(str+5) != '-' && *(str+5) != '\0') // xxx.conf or xxx.conf-i
332 continue;
333 cInstanceFilePath = g_strdup_printf ("%s/%s", cUserDataDirPath, cFileName);
334 gldi_module_instance_new (module, cInstanceFilePath); // takes ownership of 'cInstanceFilePath'.
335 n ++;
336 }
337 g_dir_close (dir);
338 }
339 else // only 1 conf file possible.
340 {
341 gchar *cConfFilePath = g_strdup_printf ("%s/%s", cUserDataDirPath, module->pVisitCard->cConfFileName);
342 if (g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))
343 {
344 gldi_module_instance_new (module, cConfFilePath);
345 n = 1;
346 }
347 else
348 {
349 g_free (cConfFilePath);
350 }
351 }
352
353 // if no conf file was present, copy the default one and instanciate the module with it.
354 if (n == 0) // no conf file was present.
355 {
356 gchar *cConfFilePath = g_strdup_printf ("%s/%s", cUserDataDirPath, module->pVisitCard->cConfFileName);
357 gboolean r = cairo_dock_copy_file (module->cConfFilePath, cConfFilePath);
358 if (! r) // the copy failed.
359 {
360 cd_warning ("couldn't copy %s into %s; check permissions and file's existence", module->cConfFilePath, cUserDataDirPath);
361 g_free (cConfFilePath);
362 g_free (cUserDataDirPath);
363 return;
364 }
365 else
366 {
367 gldi_module_instance_new (module, cConfFilePath);
368 }
369 }
370
371 g_free (cUserDataDirPath);
372 }
373 else // the module has no conf file, just instanciate it once.
374 {
375 gldi_module_instance_new (module, NULL);
376 }
377 }
378
gldi_module_deactivate(GldiModule * module)379 void gldi_module_deactivate (GldiModule *module) // stop all instances of a module
380 {
381 g_return_if_fail (module != NULL);
382 cd_debug ("%s (%s, %s)", __func__, module->pVisitCard->cModuleName, module->cConfFilePath);
383 GList *pInstances = module->pInstancesList;
384 module->pInstancesList = NULL; // set to NULL already so that notifications don't get fooled. This can probably be avoided...
385 g_list_foreach (pInstances, (GFunc)gldi_object_unref, NULL);
386 g_list_free (pInstances);
387 gldi_object_notify (module, NOTIFICATION_MODULE_ACTIVATED, module->pVisitCard->cModuleName, FALSE); // throw it since the list was NULL when the instances were destroyed
388 gldi_modules_write_active (); // same
389 }
390
391
gldi_modules_activate_from_list(gchar ** cActiveModuleList)392 void gldi_modules_activate_from_list (gchar **cActiveModuleList)
393 {
394 //\_______________ On active les modules auto-charges en premier.
395 gchar *cModuleName;
396 GldiModule *pModule;
397 GList *m;
398 for (m = s_AutoLoadedModules; m != NULL; m = m->next)
399 {
400 pModule = m->data;
401 if (pModule->pInstancesList == NULL) // not yet active
402 {
403 gldi_module_activate (pModule);
404 }
405 }
406
407 if (cActiveModuleList == NULL)
408 return ;
409
410 //\_______________ On active tous les autres.
411 int i;
412 for (i = 0; cActiveModuleList[i] != NULL; i ++)
413 {
414 cModuleName = cActiveModuleList[i];
415 pModule = g_hash_table_lookup (s_hModuleTable, cModuleName);
416 if (pModule == NULL)
417 {
418 cd_debug ("No such module (%s)", cModuleName);
419 continue ;
420 }
421
422 if (pModule->pInstancesList == NULL) // not yet active
423 {
424 gldi_module_activate (pModule);
425 }
426 }
427
428 // don't write down
429 if (s_iSidWriteModules != 0)
430 {
431 g_source_remove (s_iSidWriteModules);
432 s_iSidWriteModules = 0;
433 }
434 }
435
_deactivate_one_module(G_GNUC_UNUSED gchar * cModuleName,GldiModule * pModule,G_GNUC_UNUSED gpointer data)436 static void _deactivate_one_module (G_GNUC_UNUSED gchar *cModuleName, GldiModule *pModule, G_GNUC_UNUSED gpointer data)
437 {
438 if (! gldi_module_is_auto_loaded (pModule))
439 gldi_module_deactivate (pModule);
440 }
gldi_modules_deactivate_all(void)441 void gldi_modules_deactivate_all (void)
442 {
443 // first deactivate applets
444 g_hash_table_foreach (s_hModuleTable, (GHFunc)_deactivate_one_module, NULL);
445
446 // then deactivate auto-loaded modules (that have been loaded first)
447 GldiModule *pModule;
448 GList *m;
449 for (m = s_AutoLoadedModules; m != NULL; m = m->next)
450 {
451 pModule = m->data;
452 gldi_module_deactivate (pModule);
453 }
454
455 // don't write down
456 if (s_iSidWriteModules != 0)
457 {
458 g_source_remove (s_iSidWriteModules);
459 s_iSidWriteModules = 0;
460 }
461 }
462
463
gldi_module_add_conf_file(GldiModule * pModule)464 gchar *gldi_module_add_conf_file (GldiModule *pModule)
465 {
466 gchar *cUserDataDirPath = gldi_module_get_config_dir (pModule);
467 if (cUserDataDirPath == NULL)
468 return NULL;
469
470 // find a name that doesn't exist yet in the config dir.
471 gchar *cConfFilePath;
472 int i = 0;
473 do
474 {
475 if (i == 0)
476 cConfFilePath = g_strdup_printf ("%s/%s", cUserDataDirPath, pModule->pVisitCard->cConfFileName);
477 else
478 cConfFilePath = g_strdup_printf ("%s/%s-%d", cUserDataDirPath, pModule->pVisitCard->cConfFileName, i);
479 if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))
480 break;
481 g_free (cConfFilePath);
482 i ++;
483 } while (1);
484
485 // copy one of the instances conf file, or the default one.
486 GldiModuleInstance *pFirstInstance = NULL;
487 if (pModule->pInstancesList != NULL)
488 {
489 GList *last = g_list_last (pModule->pInstancesList);
490 pFirstInstance = last->data; // instances are prepended.
491
492 cairo_dock_add_conf_file (pFirstInstance->cConfFilePath, cConfFilePath);
493
494 if (pFirstInstance->pDesklet) // prevent desklets from overlapping.
495 {
496 int iX2, iX = pFirstInstance->pContainer->iWindowPositionX;
497 int iWidth = pFirstInstance->pContainer->iWidth;
498 if (iX + iWidth/2 <= gldi_desktop_get_width()/2) // desklet on the left, we place the new one on its right.
499 iX2 = iX + iWidth;
500 else // desklet on the right, we place the new one on its left.
501 iX2 = iX - iWidth;
502
503 int iRelativePositionX = (iX2 + iWidth/2 <= gldi_desktop_get_width()/2 ? iX2 : iX2 - gldi_desktop_get_width());
504 cairo_dock_update_conf_file (cConfFilePath,
505 G_TYPE_INT, "Desklet", "x position", iRelativePositionX,
506 G_TYPE_BOOLEAN, "Desklet", "locked", FALSE, // we'll probably want to move it
507 G_TYPE_BOOLEAN, "Desklet", "no input", FALSE,
508 G_TYPE_INVALID);
509 }
510 }
511 else // no instance yet, just copy the default conf file.
512 {
513 cairo_dock_add_conf_file (pModule->cConfFilePath, cConfFilePath);
514 }
515
516 g_free (cUserDataDirPath);
517
518 return cConfFilePath;
519 }
520
gldi_module_add_instance(GldiModule * pModule)521 void gldi_module_add_instance (GldiModule *pModule)
522 {
523 // check that the module is already active
524 if (pModule->pInstancesList == NULL)
525 {
526 cd_warning ("This module has not been instanciated yet");
527 return ;
528 }
529
530 // check that the module can be multi-instanciated
531 if (! pModule->pVisitCard->bMultiInstance)
532 {
533 cd_warning ("This module can't be instanciated more than once");
534 return ;
535 }
536
537 // add a conf file
538 gchar *cInstanceFilePath = gldi_module_add_conf_file (pModule);
539
540 // create an instance for it
541 gldi_module_instance_new (pModule, cInstanceFilePath); // takes ownership of 'cInstanceFilePath'.
542 }
543
544
545 //////////////////
546 /// GET CONFIG ///
547 //////////////////
548
get_config(GKeyFile * pKeyFile,GldiModulesParam * pModules)549 static gboolean get_config (GKeyFile *pKeyFile, GldiModulesParam *pModules)
550 {
551 gboolean bFlushConfFileNeeded = FALSE;
552
553 gsize length=0;
554 pModules->cActiveModuleList = cairo_dock_get_string_list_key_value (pKeyFile, "System", "modules", &bFlushConfFileNeeded, &length, NULL, "Applets", "modules_0");
555
556 return bFlushConfFileNeeded;
557 }
558
559 ////////////////////
560 /// RESET CONFIG ///
561 ////////////////////
562
reset_config(GldiModulesParam * pModules)563 static void reset_config (GldiModulesParam *pModules)
564 {
565 g_free (pModules->cActiveModuleList);
566 }
567
568 ////////////
569 /// INIT ///
570 ////////////
571
init(void)572 static void init (void)
573 {
574 s_hModuleTable = g_hash_table_new_full (g_str_hash,
575 g_str_equal,
576 NULL, // module name (points directly on the 'cModuleName' field of the module).
577 NULL); // module
578 }
579
580 ///////////////
581 /// MANAGER ///
582 ///////////////
583
init_object(GldiObject * obj,gpointer attr)584 static void init_object (GldiObject *obj, gpointer attr)
585 {
586 GldiModule *pModule = (GldiModule*)obj;
587 GldiModuleAttr *mattr = (GldiModuleAttr*)attr;
588
589 // check everything is ok
590 g_return_if_fail (mattr != NULL && mattr->pVisitCard != NULL && mattr->pVisitCard->cModuleName);
591
592 if (g_hash_table_lookup (s_hModuleTable, mattr->pVisitCard->cModuleName) != NULL)
593 {
594 cd_warning ("a module with the name '%s' is already registered", mattr->pVisitCard->cModuleName);
595 return;
596 }
597
598 // set params
599 pModule->pVisitCard = mattr->pVisitCard;
600 mattr->pVisitCard = NULL;
601 pModule->pInterface = mattr->pInterface;
602 mattr->pInterface = NULL;
603 if (pModule->cConfFilePath == NULL && pModule->pVisitCard->cConfFileName)
604 pModule->cConfFilePath = g_strdup_printf ("%s/%s", pModule->pVisitCard->cShareDataDir, pModule->pVisitCard->cConfFileName);
605
606 // register the module
607 g_hash_table_insert (s_hModuleTable, (gpointer)pModule->pVisitCard->cModuleName, pModule);
608
609 if (gldi_module_is_auto_loaded (pModule)) // a module that doesn't have an init/stop entry point, or that extends a manager; we'll activate it automatically (and before the others).
610 s_AutoLoadedModules = g_list_prepend (s_AutoLoadedModules, pModule);
611
612 // notify everybody
613 gldi_object_notify (&myModuleObjectMgr, NOTIFICATION_MODULE_REGISTERED, pModule->pVisitCard->cModuleName, TRUE);
614 }
615
reset_object(GldiObject * obj)616 static void reset_object (GldiObject *obj)
617 {
618 GldiModule *pModule = (GldiModule*)obj;
619 if (pModule->pVisitCard == NULL) // we didn't register it, pass
620 return;
621
622 // deactivate the module, if it was active
623 gldi_module_deactivate (pModule);
624
625 // unregister the module
626 g_hash_table_remove (s_hModuleTable, pModule->pVisitCard->cModuleName);
627
628 // notify everybody
629 gldi_object_notify (&myModuleObjectMgr, NOTIFICATION_MODULE_REGISTERED, pModule->pVisitCard->cModuleName, FALSE);
630
631 // free data
632 if (pModule->handle)
633 dlclose (pModule->handle);
634 g_free (pModule->pInterface);
635 cairo_dock_free_visit_card (pModule->pVisitCard);
636 }
637
reload_object(GldiObject * obj,gboolean bReloadConf,G_GNUC_UNUSED GKeyFile * pKeyFile)638 static GKeyFile* reload_object (GldiObject *obj, gboolean bReloadConf, G_GNUC_UNUSED GKeyFile *pKeyFile)
639 {
640 GldiModule *pModule = (GldiModule*)obj;
641 GList *pElement;
642 GldiModuleInstance *pInstance;
643 for (pElement = pModule->pInstancesList; pElement != NULL; pElement = pElement->next)
644 {
645 pInstance = pElement->data;
646 gldi_object_reload (GLDI_OBJECT(pInstance), bReloadConf);
647 }
648 return NULL;
649 }
650
gldi_register_modules_manager(void)651 void gldi_register_modules_manager (void)
652 {
653 // Manager
654 memset (&myModulesMgr, 0, sizeof (GldiManager));
655 gldi_object_init (GLDI_OBJECT(&myModulesMgr), &myManagerObjectMgr, NULL);
656 myModulesMgr.cModuleName = "Modules";
657 // interface
658 myModulesMgr.init = init;
659 myModulesMgr.load = NULL;
660 myModulesMgr.unload = NULL;
661 myModulesMgr.reload = (GldiManagerReloadFunc)NULL;
662 myModulesMgr.get_config = (GldiManagerGetConfigFunc)get_config;
663 myModulesMgr.reset_config = (GldiManagerResetConfigFunc)reset_config;
664 // Config
665 memset (&myModulesParam, 0, sizeof (GldiModulesParam));
666 myModulesMgr.pConfig = (GldiManagerConfigPtr)&myModulesParam;
667 myModulesMgr.iSizeOfConfig = sizeof (GldiModulesParam);
668 // data
669 myModulesMgr.pData = (GldiManagerDataPtr)NULL;
670 myModulesMgr.iSizeOfData = 0;
671
672 // Object Manager
673 memset (&myModuleObjectMgr, 0, sizeof (GldiObjectManager));
674 myModuleObjectMgr.cName = "Module";
675 myModuleObjectMgr.iObjectSize = sizeof (GldiModule);
676 // interface
677 myModuleObjectMgr.init_object = init_object;
678 myModuleObjectMgr.reset_object = reset_object;
679 myModuleObjectMgr.reload_object = reload_object;
680 // signals
681 gldi_object_install_notifications (GLDI_OBJECT(&myModuleObjectMgr), NB_NOTIFICATIONS_MODULES);
682 }
683