1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
15  *
16  *  Copyright (C) 2006-2016 XNeur Team
17  *
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <stdlib.h>
25 #include <strings.h>
26 #include <dlfcn.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include "plugin.h"
31 
32 #ifdef WITH_PLUGINS
33 
34 #include "types.h"
35 #include "log.h"
36 
37 extern struct _xneur_config *xconfig;
38 
plugin_add(struct _plugin * p,char * plugin_name)39 void plugin_add(struct _plugin *p, char* plugin_name)
40 {
41 	void *tmp = realloc(p->plugin, (p->plugin_count + 1) * sizeof(struct _plugin_functions));
42 	if (tmp == NULL)
43 		return;
44 	p->plugin = (struct _plugin_functions *)tmp;
45 
46 	size_t len = strlen(XNEUR_PLUGIN_DIR) + strlen(plugin_name) + 2;
47 	char * plugin_file = malloc(sizeof(char)*len);
48 	if (plugin_file == NULL)
49 		return;
50 	snprintf(plugin_file, len, "%s/%s", XNEUR_PLUGIN_DIR, plugin_name);
51 	p->plugin[p->plugin_count].module = dlopen(plugin_file, RTLD_NOW);
52 
53 	if(!p->plugin[p->plugin_count].module)
54 	{
55 		log_message (ERROR, "Can't load module %s", plugin_file);
56 		free(plugin_file);
57 		return;
58 	}
59 
60 	free(plugin_file);
61 
62 	/* Get functions adresses */
63 	p->plugin[p->plugin_count].on_init = NULL;
64 	p->plugin[p->plugin_count].on_init = dlsym(p->plugin[p->plugin_count].module, "on_init");
65 
66 	p->plugin[p->plugin_count].on_fini = NULL;
67 	p->plugin[p->plugin_count].on_fini = dlsym(p->plugin[p->plugin_count].module, "on_fini");
68 
69 	p->plugin[p->plugin_count].on_xneur_start = NULL;
70 	p->plugin[p->plugin_count].on_xneur_start = dlsym(p->plugin[p->plugin_count].module, "on_xneur_start");
71 
72 	p->plugin[p->plugin_count].on_xneur_reload = NULL;
73 	p->plugin[p->plugin_count].on_xneur_reload = dlsym(p->plugin[p->plugin_count].module, "on_xneur_reload");
74 
75 	p->plugin[p->plugin_count].on_xneur_stop = NULL;
76 	p->plugin[p->plugin_count].on_xneur_stop = dlsym(p->plugin[p->plugin_count].module, "on_xneur_stop");
77 
78 	p->plugin[p->plugin_count].on_key_press = NULL;
79 	p->plugin[p->plugin_count].on_key_press = dlsym(p->plugin[p->plugin_count].module, "on_key_press");
80 
81 	p->plugin[p->plugin_count].on_key_release = NULL;
82 	p->plugin[p->plugin_count].on_key_release = dlsym(p->plugin[p->plugin_count].module, "on_key_release");
83 
84 	p->plugin[p->plugin_count].on_hotkey_action = NULL;
85 	p->plugin[p->plugin_count].on_hotkey_action = dlsym(p->plugin[p->plugin_count].module, "on_hotkey_action");
86 
87 	p->plugin[p->plugin_count].on_change_action = NULL;
88 	p->plugin[p->plugin_count].on_change_action = dlsym(p->plugin[p->plugin_count].module, "on_change_action");
89 
90 	p->plugin[p->plugin_count].on_plugin_reload = NULL;
91 	p->plugin[p->plugin_count].on_plugin_reload = dlsym(p->plugin[p->plugin_count].module, "on_plugin_reload");
92 
93 	p->plugin[p->plugin_count].on_plugin_configure = NULL;
94 	p->plugin[p->plugin_count].on_plugin_configure = dlsym(p->plugin[p->plugin_count].module, "on_plugin_configure");
95 
96 	p->plugin[p->plugin_count].on_plugin_about = NULL;
97 	p->plugin[p->plugin_count].on_plugin_about = dlsym(p->plugin[p->plugin_count].module, "on_plugin_about");
98 
99 	p->plugin[p->plugin_count].on_plugin_info = NULL;
100 	p->plugin[p->plugin_count].on_plugin_info = dlsym(p->plugin[p->plugin_count].module, "on_plugin_info");
101 
102 	// Run init of plugin
103 	p->plugin[p->plugin_count].on_init();
104 
105 	p->plugin_count++;
106 }
107 
plugin_xneur_start(struct _plugin * p)108 void plugin_xneur_start(struct _plugin *p)
109 {
110 	for (int i=0; i<p->plugin_count; i++)
111 	{
112 		if (p->plugin[i].on_xneur_start == NULL)
113 			continue;
114 
115 		p->plugin[i].on_xneur_start();
116 	}
117 }
118 
plugin_xneur_reload(struct _plugin * p)119 void plugin_xneur_reload(struct _plugin *p)
120 {
121 	for (int i=0; i<p->plugin_count; i++)
122 	{
123 		if (p->plugin[i].on_xneur_reload == NULL)
124 			continue;
125 
126 		p->plugin[i].on_xneur_reload();
127 	}
128 }
129 
plugin_xneur_stop(struct _plugin * p)130 void plugin_xneur_stop(struct _plugin *p)
131 {
132 	for (int i=0; i<p->plugin_count; i++)
133 	{
134 		if (p->plugin[i].on_xneur_stop == NULL)
135 			continue;
136 
137 		p->plugin[i].on_xneur_stop();
138 	}
139 }
140 
plugin_key_press(struct _plugin * p,KeySym key,int modifier_mask)141 void plugin_key_press(struct _plugin *p, KeySym key, int modifier_mask)
142 {
143 	for (int i=0; i<p->plugin_count; i++)
144 	{
145 		if (p->plugin[i].on_key_press == NULL)
146 			continue;
147 
148 		p->plugin[i].on_key_press(key, modifier_mask);
149 	}
150 }
151 
plugin_key_release(struct _plugin * p,KeySym key,int modifier_mask)152 void plugin_key_release(struct _plugin *p, KeySym key, int modifier_mask)
153 {
154 	for (int i=0; i<p->plugin_count; i++)
155 	{
156 		if (p->plugin[i].on_key_release == NULL)
157 			continue;
158 
159 		p->plugin[i].on_key_release(key, modifier_mask);
160 	}
161 }
162 
plugin_hotkey_action(struct _plugin * p,enum _hotkey_action ha)163 void plugin_hotkey_action(struct _plugin *p, enum _hotkey_action ha)
164 {
165 	for (int i=0; i<p->plugin_count; i++)
166 	{
167 		if (p->plugin[i].on_hotkey_action == NULL)
168 			continue;
169 
170 		p->plugin[i].on_hotkey_action(ha);
171 	}
172 }
173 
plugin_change_action(struct _plugin * p,enum _change_action ca)174 void plugin_change_action(struct _plugin *p, enum _change_action ca)
175 {
176 	for (int i=0; i<p->plugin_count; i++)
177 	{
178 		if (p->plugin[i].on_change_action == NULL)
179 			continue;
180 
181 		p->plugin[i].on_change_action(ca);
182 	}
183 }
184 
plugin_plugin_reload(struct _plugin * p)185 void plugin_plugin_reload(struct _plugin *p)
186 {
187 	for (int i=0; i<p->plugin_count; i++)
188 	{
189 		if (p->plugin[i].on_plugin_reload == NULL)
190 			continue;
191 
192 		p->plugin[i].on_plugin_reload();
193 		dlclose(p->plugin[i].module);
194 	}
195 
196 	free(p->plugin);
197 }
198 
plugin_plugin_configure(struct _plugin * p)199 void plugin_plugin_configure(struct _plugin *p)
200 {
201 	for (int i=0; i<p->plugin_count; i++)
202 	{
203 		if (p->plugin[i].on_plugin_configure == NULL)
204 			continue;
205 
206 		p->plugin[i].on_plugin_configure();
207 	}
208 }
209 
plugin_plugin_about(struct _plugin * p)210 void plugin_plugin_about(struct _plugin *p)
211 {
212 	for (int i=0; i<p->plugin_count; i++)
213 	{
214 		if (p->plugin[i].on_plugin_about == NULL)
215 			continue;
216 
217 		p->plugin[i].on_plugin_about();
218 	}
219 }
220 
plugin_plugin_info(struct _plugin * p)221 void plugin_plugin_info(struct _plugin *p)
222 {
223 	for (int i=0; i<p->plugin_count; i++)
224 	{
225 		if (p->plugin[i].on_plugin_info == NULL)
226 			continue;
227 
228 		p->plugin[i].on_plugin_info();
229 	}
230 }
231 
plugin_uninit(struct _plugin * p)232 void plugin_uninit(struct _plugin *p)
233 {
234 	for (int i=0; i<p->plugin_count; i++)
235 	{
236 		if (p->plugin[i].on_fini != NULL)
237 			p->plugin[i].on_fini();
238 
239 		dlclose(p->plugin[i].module);
240 	}
241 
242 	free(p->plugin);
243 	free(p);
244 
245 	log_message(DEBUG, _("Plugins is freed"));
246 }
247 
248 #else /* WITH_PLUGINS */
249 
plugin_add(struct _plugin * p,char * plugin_name)250 void plugin_add(struct _plugin *p, char* plugin_name)
251 {
252 	if (p || plugin_name) {};
253 }
254 
plugin_xneur_start(struct _plugin * p)255 void plugin_xneur_start(struct _plugin *p)
256 {
257 	if (p) {};
258 }
259 
plugin_xneur_reload(struct _plugin * p)260 void plugin_xneur_reload(struct _plugin *p)
261 {
262 	if (p) {};
263 }
264 
plugin_xneur_stop(struct _plugin * p)265 void plugin_xneur_stop(struct _plugin *p)
266 {
267 	if (p) {};
268 }
269 
plugin_key_press(struct _plugin * p,KeySym key,int modifier_mask)270 void plugin_key_press(struct _plugin *p, KeySym key, int modifier_mask)
271 {
272 	if (p || key || modifier_mask) {};
273 }
274 
plugin_key_release(struct _plugin * p,KeySym key,int modifier_mask)275 void plugin_key_release(struct _plugin *p, KeySym key, int modifier_mask)
276 {
277 	if (p || key || modifier_mask) {};
278 }
279 
plugin_hotkey_action(struct _plugin * p,enum _hotkey_action ha)280 void plugin_hotkey_action(struct _plugin *p, enum _hotkey_action ha)
281 {
282 	if (p || ha) {};
283 }
284 
plugin_change_action(struct _plugin * p,enum _change_action ca)285 void plugin_change_action(struct _plugin *p, enum _change_action ca)
286 {
287 	if (p || ca) {};
288 }
289 
plugin_plugin_reload(struct _plugin * p)290 void plugin_plugin_reload(struct _plugin *p)
291 {
292 	if (p) {};
293 }
294 
plugin_plugin_configure(struct _plugin * p)295 void plugin_plugin_configure(struct _plugin *p)
296 {
297 	if (p) {};
298 }
299 
plugin_plugin_about(struct _plugin * p)300 void plugin_plugin_about(struct _plugin *p)
301 {
302 	if (p) {};
303 }
304 
plugin_plugin_info(struct _plugin * p)305 void plugin_plugin_info(struct _plugin *p)
306 {
307 	if (p) {};
308 }
309 
plugin_uninit(struct _plugin * p)310 void plugin_uninit(struct _plugin *p)
311 {
312 	if (p) {};
313 }
314 
315 #endif /* WITH_PLUGINS */
316 
plugin_init(void)317 struct _plugin* plugin_init(void)
318 {
319 	struct _plugin *p = (struct _plugin *) malloc(sizeof(struct _plugin));
320 	bzero(p, sizeof(struct _plugin));
321 
322 	p->plugin = (struct _plugin_functions *) malloc(sizeof(struct _plugin_functions));
323 	bzero(p->plugin, sizeof(struct _plugin_functions));
324 
325 	// Function mapping
326 
327 	p->add = plugin_add;
328 
329 	p->xneur_start = plugin_xneur_start;
330 	p->xneur_reload = plugin_xneur_reload;
331 	p->xneur_stop = plugin_xneur_stop;
332 	p->key_press = plugin_key_press;
333 	p->key_release = plugin_key_release;
334 	p->hotkey_action = plugin_hotkey_action;
335 	p->change_action = plugin_change_action;
336 	p->plugin_reload = plugin_plugin_reload;
337 	p->plugin_configure = plugin_plugin_configure;
338 	p->plugin_about = plugin_plugin_about;
339 
340 	p->uninit		= plugin_uninit;
341 
342 	return p;
343 }
344