]> Dogcows Code - chaz/openbox/blob - openbox/plugin.c
load menu plugins automatically from whats in the menu file
[chaz/openbox] / openbox / plugin.c
1 #include "plugins/interface.h"
2 #include "parser/parse.h"
3
4 #include <glib.h>
5 #include <gmodule.h>
6
7 typedef struct {
8 GModule *module;
9 gchar *name;
10
11 gboolean started;
12
13 PluginSetupConfig config;
14 PluginStartup startup;
15 PluginShutdown shutdown;
16 } Plugin;
17
18 static gpointer load_sym(GModule *module, gchar *name, gchar *symbol,
19 gboolean allow_fail)
20 {
21 gpointer var;
22 if (!g_module_symbol(module, symbol, &var)) {
23 if (!allow_fail)
24 g_warning("Failed to load symbol '%s' from plugin '%s'",
25 symbol, name);
26 var = NULL;
27 }
28 return var;
29 }
30
31 static Plugin *plugin_new(gchar *name)
32 {
33 Plugin *p;
34 gchar *path;
35
36 p = g_new(Plugin, 1);
37 p->started = FALSE;
38
39 path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
40 NULL);
41 p->module = g_module_open(path, 0);
42 g_free(path);
43
44 if (p->module == NULL) {
45 path = g_build_filename(PLUGINDIR, name, NULL);
46 p->module = g_module_open(path, 0);
47 g_free(path);
48 }
49
50 if (p->module == NULL) {
51 g_warning(g_module_error());
52 g_free(p);
53 return NULL;
54 }
55
56 p->config = (PluginSetupConfig)load_sym(p->module, name,
57 "plugin_setup_config", FALSE);
58 p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup",
59 FALSE);
60 p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown",
61 FALSE);
62
63 if (p->config == NULL || p->startup == NULL || p->shutdown == NULL) {
64 g_module_close(p->module);
65 g_free(p);
66 return NULL;
67 }
68
69 p->name = g_strdup(name);
70 return p;
71 }
72
73 static void plugin_free(Plugin *p)
74 {
75 p->shutdown();
76
77 g_free(p->name);
78 g_module_close(p->module);
79 }
80
81
82 static GData *plugins = NULL;
83
84 void plugin_startup()
85 {
86 g_datalist_init(&plugins);
87 }
88
89 void plugin_shutdown()
90 {
91 g_datalist_clear(&plugins);
92 }
93
94 gboolean plugin_open(gchar *name, ObParseInst *i)
95 {
96 Plugin *p;
97
98 if (g_datalist_get_data(&plugins, name) != NULL)
99 return TRUE;
100
101 p = plugin_new(name);
102 if (p == NULL) {
103 g_warning("failed to load plugin '%s'", name);
104 return FALSE;
105 }
106 p->config(i);
107
108 g_datalist_set_data_full(&plugins, name, p, (GDestroyNotify) plugin_free);
109 return TRUE;
110 }
111
112 static void foreach_start(GQuark key, Plugin *p, gpointer *foo)
113 {
114 if (!p->started) {
115 p->startup();
116 p->started = TRUE;
117 }
118 }
119
120 void plugin_startall()
121 {
122 g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL);
123 }
124
125 void plugin_start(gchar *name)
126 {
127 Plugin *p;
128
129 if (!(p = g_datalist_get_data(&plugins, name))) {
130 g_warning("Tried to start plugin '%s' but it is not loaded", name);
131 return;
132 }
133 if (!p->started) {
134 p->startup();
135 p->started = TRUE;
136 }
137 }
138
139 void plugin_loadall(ObParseInst *i)
140 {
141 GIOChannel *io;
142 GError *err;
143 gchar *path, *name;
144
145 path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL);
146 err = NULL;
147 io = g_io_channel_new_file(path, "r", &err);
148 g_free(path);
149
150 if (io == NULL) {
151 path = g_build_filename(RCDIR, "pluginrc", NULL);
152 err = NULL;
153 io = g_io_channel_new_file(path, "r", &err);
154 g_free(path);
155 }
156
157 if (io == NULL) {
158 /* load the default plugins */
159 plugin_open("placement", i);
160 } else {
161 /* load the plugins in the rc file */
162 while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
163 G_IO_STATUS_NORMAL) {
164 g_strstrip(name);
165 if (name[0] != '\0' && name[0] != '#')
166 plugin_open(name, i);
167 g_free(name);
168 }
169 g_io_channel_unref(io);
170 }
171 }
This page took 0.041655 seconds and 4 git commands to generate.