/[zanavi_public1]/navit/navit/plugin.c
ZANavi

Contents of /navit/navit/plugin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 11338 byte(s)
new map version, lots of fixes and experimental new features
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <string.h>
40 #include <glib.h>
41 #include "config.h"
42 #ifdef USE_PLUGINS
43 #ifdef HAVE_GMODULE
44 #include <gmodule.h>
45 #else
46 #ifdef HAVE_API_WIN32_BASE
47 #include <windows.h>
48 #else
49 #include <dlfcn.h>
50 #endif
51 #endif
52 #endif
53 #include "plugin.h"
54 #include "file.h"
55 #define PLUGIN_C
56 #include "plugin.h"
57 #include "item.h"
58 #include "debug.h"
59
60 #ifdef USE_PLUGINS
61 #ifndef HAVE_GMODULE
62 typedef void * GModule;
63 #define G_MODULE_BIND_LOCAL 1
64 #define G_MODULE_BIND_LAZY 2
65 static int
66 g_module_supported(void)
67 {
68 return 1;
69 }
70
71 #ifdef HAVE_API_WIN32_BASE
72
73 static DWORD last_error;
74 static char errormsg[64];
75
76 static void *
77 g_module_open(char *name, int flags)
78 {
79 HINSTANCE handle;
80 int len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, 0, 0);
81 wchar_t filename[len];
82 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, filename, len);
83
84 handle = LoadLibraryW (filename);
85 if (!handle)
86 last_error=GetLastError();
87 return handle;
88 }
89
90 static char *
91 g_module_error(void)
92 {
93 sprintf(errormsg,"dll error %d",(int)last_error);
94 return errormsg;
95 }
96
97 static int
98 g_module_symbol(GModule *handle, char *symbol, gpointer *addr)
99 {
100 #ifdef HAVE_API_WIN32_CE
101 int len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, symbol, -1, 0, 0);
102 wchar_t wsymbol[len+1];
103 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, symbol, -1, wsymbol, len);
104 *addr=GetProcAddress ((HANDLE)handle, wsymbol);
105 #else
106 *addr=GetProcAddress ((HANDLE)handle, symbol);
107 #endif
108 if (*addr)
109 return 1;
110 last_error=GetLastError();
111 return 0;
112 }
113
114 static void
115 g_module_close(GModule *handle)
116 {
117 FreeLibrary((HANDLE)handle);
118 }
119
120 #else
121 static void *
122 g_module_open(char *name, int flags)
123 {
124 return dlopen(name,
125 (flags & G_MODULE_BIND_LAZY ? RTLD_LAZY : RTLD_NOW) |
126 (flags & G_MODULE_BIND_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL));
127 }
128
129 static char *
130 g_module_error(void)
131 {
132 return dlerror();
133 }
134
135 static int
136 g_module_symbol(GModule *handle, char *symbol, gpointer *addr)
137 {
138 *addr=dlsym(handle, symbol);
139 return (*addr != NULL);
140 }
141
142 static void
143 g_module_close(GModule *handle)
144 {
145 dlclose(handle);
146 }
147 #endif
148 #endif
149 #endif
150
151 struct plugin
152 {
153 int active;
154 int lazy;
155 int ondemand;
156 char *name;
157 #ifdef USE_PLUGINS
158 GModule *mod;
159 #endif
160 void (*init)(void);
161 };
162
163 struct plugins
164 {
165 GHashTable *hash;
166 GList *list;
167 }*pls;
168
169 static struct plugin *
170 plugin_new_from_path(char *plugin)
171 {
172 #ifdef USE_PLUGINS
173 struct plugin *ret;
174 if (! g_module_supported())
175 {
176 return NULL;
177 }
178 ret=g_new0(struct plugin, 1);
179 ret->name=g_strdup(plugin);
180 return ret;
181 #else
182 return NULL;
183 #endif
184 }
185
186 int plugin_load(struct plugin *pl)
187 {
188 #ifdef USE_PLUGINS
189 gpointer init;
190
191 GModule *mod;
192
193 if (pl->mod)
194 {
195 dbg(0,"can't load '%s', already loaded\n", pl->name);
196 return 0;
197 }
198 mod=g_module_open(pl->name, G_MODULE_BIND_LOCAL | (pl->lazy ? G_MODULE_BIND_LAZY : 0));
199 if (! mod)
200 {
201 dbg(0,"can't load '%s', Error '%s'\n", pl->name, g_module_error());
202 return 0;
203 }
204 if (!g_module_symbol(mod, "plugin_init", &init))
205 {
206 dbg(0,"can't load '%s', plugin_init not found\n", pl->name);
207 g_module_close(mod);
208 return 0;
209 }
210 else
211 {
212 pl->mod=mod;
213 pl->init=init;
214 }
215 return 1;
216 #else
217 return 0;
218 #endif
219 }
220
221 char *
222 plugin_get_name(struct plugin *pl)
223 {
224 return pl->name;
225 }
226
227 int plugin_get_active(struct plugin *pl)
228 {
229 return pl->active;
230 }
231
232 void plugin_set_active(struct plugin *pl, int active)
233 {
234 pl->active = active;
235 }
236
237 void plugin_set_lazy(struct plugin *pl, int lazy)
238 {
239 pl->lazy = lazy;
240 }
241
242 #ifdef USE_PLUGINS
243 static int
244 plugin_get_ondemand(struct plugin *pl)
245 {
246 return pl->ondemand;
247 }
248 #endif
249
250 static void plugin_set_ondemand(struct plugin *pl, int ondemand)
251 {
252 pl->ondemand = ondemand;
253 }
254
255 void plugin_call_init(struct plugin *pl)
256 {
257 pl->init();
258 }
259
260 void plugin_unload(struct plugin *pl)
261 {
262 #ifdef USE_PLUGINS
263 g_module_close(pl->mod);
264 pl->mod=NULL;
265 #endif
266 }
267
268 void plugin_destroy(struct plugin *pl)
269 {
270 g_free(pl);
271 }
272
273 struct plugins *
274 plugins_new(void)
275 {
276 //dbg(0, "enter\n");
277 struct plugins *ret=g_new0(struct plugins, 1);
278 ret->hash = g_hash_table_new(g_str_hash, g_str_equal);
279 pls = ret;
280 //dbg(0, "leave\n");
281 return ret;
282 }
283
284 char *replace_func(char *st, char *orig, char *repl)
285 {
286 static char buffer[4096];
287 char *ch;
288 if (!(ch = strstr(st, orig)))
289 return st;
290 strncpy(buffer, st, ch - st);
291 buffer[ch - st] = 0;
292 sprintf(buffer + (ch - st), "%s%s", repl, ch + strlen(orig));
293 return buffer;
294 }
295
296 struct plugin *
297 plugin_new(struct attr *parent, struct attr **attrs)
298 {
299 #ifdef USE_PLUGINS
300
301 //dbg(0,"enter\n");
302
303 struct attr *path_attr, *attr;
304 struct file_wordexp *we;
305 int active=1; // default active
306 int lazy=0, ondemand=0;
307 int i, count;
308 char **array;
309 char *name;
310 struct plugin *pl=NULL;
311 struct plugins *pls=NULL;
312
313 if (parent)
314 {
315 pls=parent->u.plugins;
316 }
317
318 if (! (path_attr=attr_search(attrs, NULL, attr_path)))
319 {
320 dbg(0,"missing path\n");
321 return NULL;
322 }
323
324 if ( (attr=attr_search(attrs, NULL, attr_active)))
325 {
326 active=attr->u.num;
327 }
328
329 if ( (attr=attr_search(attrs, NULL, attr_lazy)))
330 {
331 lazy=attr->u.num;
332 }
333
334 if ( (attr=attr_search(attrs, NULL, attr_ondemand)))
335 {
336 ondemand=attr->u.num;
337 }
338 //dbg(0, "path=\"%s\", active=%d, lazy=%d, ondemand=%d\n",path_attr->u.str, active, lazy, ondemand);
339
340 name = replace_func(path_attr->u.str, "$NAVIT_PREFIX", "/data/data/com.zoffcc.applications.zanavi");
341
342 //dbg(0,"pp 001 name=%s\n", name);
343 //dbg(0,"pp 002\n");
344 //dbg(0,"pp 003\n");
345 //dbg(0,"pp 004\n");
346 //dbg(0,"expanded to %d words\n",count);
347
348 #if 0
349 if (count != 1 || file_exists(array[0]))
350 {
351 dbg(0,"pl 001\n");
352 for (i = 0; i < count; i++)
353 {
354 dbg(0,"pl 002\n");
355 name=array[i];
356 dbg(0,"name[%d]='%s'\n", i, name);
357 if (! (pls && (pl=g_hash_table_lookup(pls->hash, name))))
358 {
359 dbg(0,"pl 003\n");
360 pl=plugin_new_from_path(name);
361 dbg(0,"pl 004\n");
362 if (! pl)
363 {
364 dbg(0,"failed to create plugin '%s'\n", name);
365 continue;
366 }
367 if (pls)
368 {
369 dbg(0,"pl 005\n");
370 g_hash_table_insert(pls->hash, plugin_get_name(pl), pl);
371 pls->list=g_list_append(pls->list, pl);
372 dbg(0,"pl 006\n");
373 }
374 }
375 else
376 {
377 if (pls)
378 {
379 dbg(0,"pl 007\n");
380 pls->list=g_list_remove(pls->list, pl);
381 pls->list=g_list_append(pls->list, pl);
382 dbg(0,"pl 008\n");
383 }
384 }
385
386 dbg(0,"pl 009\n");
387 plugin_set_active(pl, active);
388 plugin_set_lazy(pl, lazy);
389 plugin_set_ondemand(pl, ondemand);
390 dbg(0,"pl 010\n");
391
392 if (!pls && active)
393 {
394 dbg(0,"pl 011\n");
395 if (!plugin_load(pl))
396 {
397 plugin_set_active(pl, 0);
398 }
399 else
400 {
401 plugin_call_init(pl);
402 }
403 dbg(0,"pl 012\n");
404 }
405 }
406 }
407 dbg(0,"pl 013\n");
408 file_wordexp_destroy(we);
409 dbg(0,"leave\n");
410 #endif
411
412 //dbg(0,"pl 002\n");
413 //dbg(0,"name='%s'\n", name);
414 if (! (pls && (pl=g_hash_table_lookup(pls->hash, name))))
415 {
416 //dbg(0,"pl 003\n");
417 pl=plugin_new_from_path(name);
418 //dbg(0,"pl 004\n");
419 if (! pl)
420 {
421 dbg(0,"failed to create plugin '%s'\n", name);
422 // continue;
423 }
424 if (pls)
425 {
426 //dbg(0,"pl 005\n");
427 g_hash_table_insert(pls->hash, plugin_get_name(pl), pl);
428 pls->list=g_list_append(pls->list, pl);
429 //dbg(0,"pl 006\n");
430 }
431 }
432 else
433 {
434 if (pls)
435 {
436 //dbg(0,"pl 007\n");
437 pls->list=g_list_remove(pls->list, pl);
438 pls->list=g_list_append(pls->list, pl);
439 //dbg(0,"pl 008\n");
440 }
441 }
442
443 //dbg(0,"pl 009\n");
444 plugin_set_active(pl, active);
445 plugin_set_lazy(pl, lazy);
446 plugin_set_ondemand(pl, ondemand);
447 //dbg(0,"pl 010\n");
448
449 if (!pls && active)
450 {
451 //dbg(0,"pl 011\n");
452 if (!plugin_load(pl))
453 {
454 plugin_set_active(pl, 0);
455 }
456 else
457 {
458 plugin_call_init(pl);
459 }
460 //dbg(0,"pl 012\n");
461 }
462
463 return pl;
464 #else
465 return 0;
466 #endif
467 }
468
469 void plugins_init(struct plugins *pls)
470 {
471 #ifdef USE_PLUGINS
472
473 //dbg(0,"enter\n");
474
475 struct plugin *pl;
476 GList *l;
477
478 l=pls->list;
479 while (l)
480 {
481 pl=l->data;
482 if (! plugin_get_ondemand(pl))
483 {
484 if (plugin_get_active(pl))
485 {
486 //dbg(0,"plugin_load start\n");
487 if (!plugin_load(pl))
488 {
489 //dbg(0,"plugin_set_active start\n");
490 plugin_set_active(pl, 0);
491 //dbg(0,"plugin_set_end start\n");
492 }
493 //dbg(0,"plugin_load end\n");
494 }
495
496 if (plugin_get_active(pl))
497 {
498 //dbg(0,"plugin_call_init start\n");
499 plugin_call_init(pl);
500 //dbg(0,"plugin_call_init end\n");
501 }
502 }
503 l=g_list_next(l);
504 }
505
506 //dbg(0,"leave\n");
507 #endif
508 }
509
510 void plugins_destroy(struct plugins *pls)
511 {
512 GList *l;
513 struct plugin *pl;
514
515 l = pls->list;
516 while (l)
517 {
518 pl = l->data;
519 plugin_unload(pl);
520 plugin_destroy(pl);
521 }
522 g_list_free(pls->list);
523 g_hash_table_destroy(pls->hash);
524 g_free(pls);
525 }
526
527 void *
528 plugin_get_type(enum plugin_type type, const char *type_name, const char *name)
529 {
530 GList *l, *lpls;
531 struct name_val *nv;
532 struct plugin *pl;
533 char *mod_name, *filename = NULL, *corename = NULL;
534
535 //dbg(1, "type=\"%s\", name=\"%s\"\n", type_name, name);
536
537 l = plugin_types[type];
538 while (l)
539 {
540 nv = l->data;
541 if (!g_ascii_strcasecmp(nv->name, name))
542 return nv->val;
543 l = g_list_next(l);
544 }
545 if (!pls)
546 return NULL;
547 lpls = pls->list;
548 filename = g_strjoin("", "lib", type_name, "_", name, NULL);
549 corename = g_strjoin("", "lib", type_name, "_", "core", NULL);
550 while (lpls)
551 {
552 pl = lpls->data;
553 if ((mod_name = g_strrstr(pl->name, "/")))
554 mod_name++;
555 else
556 mod_name = pl->name;
557 //dbg(2, "compare '%s' with '%s'\n", mod_name, filename);
558 if (!g_ascii_strncasecmp(mod_name, filename, strlen(filename)) || !g_ascii_strncasecmp(mod_name, corename, strlen(corename)))
559 {
560 //dbg(1, "Loading module \"%s\"\n", pl->name);
561 if (plugin_get_active(pl))
562 if (!plugin_load(pl))
563 plugin_set_active(pl, 0);
564 if (plugin_get_active(pl))
565 plugin_call_init(pl);
566 l = plugin_types[type];
567 while (l)
568 {
569 nv = l->data;
570 if (!g_ascii_strcasecmp(nv->name, name))
571 {
572 g_free(filename);
573 g_free(corename);
574 return nv->val;
575 }
576 l = g_list_next(l);
577 }
578 }
579 lpls = g_list_next(lpls);
580 }
581 g_free(filename);
582 g_free(corename);
583 return NULL;
584 }

   
Visit the ZANavi Wiki