plugins work.
[dana/openbox.git] / openbox / plugin.c
1 #include <glib.h>
2 #include <gmodule.h>
3
4 typedef void (*PluginStartup)();
5 typedef void (*PluginShutdown)();
6
7 typedef struct {
8     GModule *module;
9     char *name;
10
11     PluginStartup startup;
12     PluginShutdown shutdown;
13 } Plugin;
14
15 static gpointer load_sym(GModule *module, char *name, char *symbol)
16 {
17     gpointer var = NULL;
18     if (!g_module_symbol(module, symbol, &var))
19         g_warning("Failed to load symbol '%s' from plugin '%s'", symbol, name);
20     return var;
21 }
22
23 static Plugin *plugin_new(char *name)
24 {
25     Plugin *p;
26     char *path;
27    
28     p = g_new(Plugin, 1);
29
30     path = g_build_filename(PLUGINDIR, name, NULL);
31     p->module = g_module_open(path, G_MODULE_BIND_LAZY);
32     g_free(path);
33
34     if (p->module == NULL) {
35         path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
36                                 NULL);
37         p->module = g_module_open(path, G_MODULE_BIND_LAZY);
38         g_free(path);
39     }
40
41     if (p->module == NULL) {
42         g_free(p);
43         return NULL;
44     }
45
46     p->startup = load_sym(p->module, name, "startup");
47     p->shutdown = load_sym(p->module, name, "shutdown");
48
49     if (p->startup == NULL || p->shutdown == NULL) {
50         g_module_close(p->module);
51         g_free(p);
52         return NULL;
53     }
54
55     p->name = g_strdup(name);
56     return p;
57 }
58
59 static void plugin_free(Plugin *p)
60 {
61     p->shutdown();
62
63     g_free(p->name);
64     g_module_close(p->module);
65 }
66
67
68 static GData *plugins = NULL;
69
70 void plugin_startup()
71 {
72     g_datalist_init(&plugins);
73 }
74
75 void plugin_shutdown()
76 {
77     g_datalist_clear(&plugins);
78 }
79
80 gboolean plugin_open(char *name)
81 {
82     Plugin *p;
83
84     if (g_datalist_get_data(&plugins, name) != NULL) {
85         g_warning("plugin '%s' already loaded, can't load again", name);
86         return TRUE;
87     }
88
89     p = plugin_new(name);
90     if (p == NULL) {
91         g_warning("failed to load plugin '%s'", name);
92         return FALSE;
93     }
94
95     g_datalist_set_data_full(&plugins, name, p,  (GDestroyNotify) plugin_free);
96     p->startup();
97     return TRUE;
98 }
99
100 void plugin_close(char *name)
101 {
102     g_datalist_remove_data(&plugins, name);
103 }