Fix:Core:Replace g_warning with dbg(0, some wince fixes
[navit-package] / navit / plugin.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
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 #include <string.h>
21 #include <glib.h>
22 #include "config.h"
23 #ifdef USE_PLUGINS
24 #include <gmodule.h>
25 #endif
26 #include "plugin.h"
27 #include "file.h"
28 #define PLUGIN_C
29 #include "plugin.h"
30 #include "item.h"
31 #include "debug.h"
32
33 struct plugin {
34         int active;
35         int lazy;
36         int ondemand;
37         char *name;
38 #ifdef USE_PLUGINS
39         GModule *mod;
40 #endif
41         void (*init)(void);
42 };
43
44 struct plugins {
45         GHashTable *hash;
46         GList *list;
47 } *pls;
48
49 struct plugin *
50 plugin_new(char *plugin)
51 {
52 #ifdef USE_PLUGINS
53         struct plugin *ret;
54         if (! g_module_supported()) {
55                 return NULL;
56         }
57         ret=g_new0(struct plugin, 1);
58         ret->name=g_strdup(plugin);
59         return ret;
60 #else
61         return NULL;
62 #endif
63 }
64
65 int
66 plugin_load(struct plugin *pl)
67 {
68 #ifdef USE_PLUGINS
69         gpointer init;
70
71         GModule *mod;
72
73         if (pl->mod) {
74                 dbg(0,"can't load '%s', already loaded\n", pl->name);
75                 return 0;
76         }
77         mod=g_module_open(pl->name, G_MODULE_BIND_LOCAL | (pl->lazy ? G_MODULE_BIND_LAZY : 0));
78         if (! mod) {
79                 dbg(0,"can't load '%s', Error '%s'\n", pl->name, g_module_error());
80                 return 0;
81         }
82         if (!g_module_symbol(mod, "plugin_init", &init)) {
83                 dbg(0,"can't load '%s', plugin_init not found\n", pl->name);
84                 g_module_close(mod);
85                 return 0;
86         } else {
87                 pl->mod=mod;
88                 pl->init=init;
89         }
90         return 1;
91 #else
92         return 0;
93 #endif
94 }
95
96 char *
97 plugin_get_name(struct plugin *pl)
98 {
99         return pl->name;
100 }
101
102 int
103 plugin_get_active(struct plugin *pl)
104 {
105         return pl->active;
106 }
107
108 void
109 plugin_set_active(struct plugin *pl, int active)
110 {
111         pl->active=active;
112 }
113
114 void
115 plugin_set_lazy(struct plugin *pl, int lazy)
116 {
117         pl->lazy=lazy;
118 }
119
120 #ifdef USE_PLUGINS
121 static int
122 plugin_get_ondemand(struct plugin *pl)
123 {
124         return pl->ondemand;
125 }
126 #endif
127
128 static void
129 plugin_set_ondemand(struct plugin *pl, int ondemand)
130 {
131         pl->ondemand=ondemand;
132 }
133
134 void
135 plugin_call_init(struct plugin *pl)
136 {
137         pl->init();
138 }
139
140 void
141 plugin_unload(struct plugin *pl)
142 {
143 #ifdef USE_PLUGINS
144         g_module_close(pl->mod);
145         pl->mod=NULL;
146 #endif
147 }
148
149 void
150 plugin_destroy(struct plugin *pl)
151 {
152         g_free(pl);
153 }
154
155 struct plugins *
156 plugins_new(void)
157 {
158         struct plugins *ret=g_new0(struct plugins, 1);
159         ret->hash=g_hash_table_new(g_str_hash, g_str_equal);
160         pls=ret;
161         return ret;
162 }
163
164 void
165 plugins_add_path(struct plugins *pls, struct attr **attrs) {
166         struct attr *path_attr, *attr;
167         struct file_wordexp *we;
168         int active=1; // default active
169         int lazy=0, ondemand=0;
170         int i, count;
171         char **array;
172         char *name;
173         struct plugin *pl;
174
175         if (! (path_attr=attr_search(attrs, NULL, attr_path))) {
176                 dbg(0,"missing path\n");
177                 return;
178         }
179         if ( (attr=attr_search(attrs, NULL, attr_active))) {
180                 active=attr->u.num;
181         }
182         if ( (attr=attr_search(attrs, NULL, attr_lazy))) {
183                 lazy=attr->u.num;
184         }
185         if ( (attr=attr_search(attrs, NULL, attr_ondemand))) {
186                 ondemand=attr->u.num;
187         }
188         dbg(1, "path=\"%s\", active=%d, lazy=%d, ondemand=%d\n",path_attr->u.str, active, lazy, ondemand);
189
190         we=file_wordexp_new(path_attr->u.str);
191         count=file_wordexp_get_count(we);
192         array=file_wordexp_get_array(we);       
193         for (i = 0 ; i < count ; i++) {
194                 name=array[i];
195                 if (! (pl=g_hash_table_lookup(pls->hash, name))) {
196                         pl=plugin_new(name);
197                         if (! pl) {
198                                 dbg(0,"failed to create plugin '%s'\n", name);
199                                 continue;
200                         }
201                         g_hash_table_insert(pls->hash, plugin_get_name(pl), pl);
202                         pls->list=g_list_append(pls->list, pl);
203                 } else {
204                         pls->list=g_list_remove(pls->list, pl);
205                         pls->list=g_list_append(pls->list, pl);
206                 }
207                 plugin_set_active(pl, active);
208                 plugin_set_lazy(pl, lazy);
209                 plugin_set_ondemand(pl, ondemand);
210         }
211         file_wordexp_destroy(we);
212 }
213
214 void
215 plugins_init(struct plugins *pls)
216 {
217 #ifdef USE_PLUGINS
218         struct plugin *pl;
219         GList *l;
220
221         l=pls->list;
222         while (l) {
223                 pl=l->data;
224                 if (! plugin_get_ondemand(pl)) {
225                         if (plugin_get_active(pl)) 
226                                 if (!plugin_load(pl)) 
227                                         plugin_set_active(pl, 0);
228                         if (plugin_get_active(pl)) 
229                                 plugin_call_init(pl);
230                 }
231                 l=g_list_next(l);
232         }
233 #endif
234 }
235
236 void
237 plugins_destroy(struct plugins *pls)
238 {
239         GList *l;
240         struct plugin *pl;
241
242         l=pls->list;
243         while (l) {
244                 pl=l->data;
245                 plugin_unload(pl);
246                 plugin_destroy(pl);
247         }
248         g_list_free(pls->list);
249         g_hash_table_destroy(pls->hash);
250         g_free(pls);
251 }
252
253         void *
254 plugin_get_type(enum plugin_type type, const char *type_name, const char *name)
255 {
256         dbg(1, "type=\"%s\", name=\"%s\"\n", type_name, name);
257         GList *l,*lpls;
258         struct name_val *nv;
259         struct plugin *pl;
260         char *mod_name, *filename=NULL, *corename=NULL;
261         l=plugin_types[type];
262         while (l) {
263                 nv=l->data;
264                 if (!g_ascii_strcasecmp(nv->name, name))
265                         return nv->val;
266                 l=g_list_next(l);
267         }
268         lpls=pls->list;
269         if(!g_ascii_strcasecmp(type_name, "map"))
270                 type_name="data";
271         filename=g_strjoin("", "lib", type_name, "_", name, NULL);
272         corename=g_strjoin("", "lib", type_name, "_", "core", NULL);
273         while (lpls) {
274                 pl=lpls->data;
275                 if ((mod_name=g_strrstr(pl->name, "/")))
276                         mod_name++;
277                 else
278                         mod_name=pl->name;
279                 if (!g_ascii_strncasecmp(mod_name, filename, strlen(filename)) || !g_ascii_strncasecmp(mod_name, corename, strlen(filename))) {
280                         dbg(0, "Loading module \"%s\"\n",pl->name) ;
281                         if (plugin_get_active(pl)) 
282                                 if (!plugin_load(pl)) 
283                                         plugin_set_active(pl, 0);
284                         if (plugin_get_active(pl)) 
285                                 plugin_call_init(pl);
286                         l=plugin_types[type];
287                         while (l) {
288                                 nv=l->data;
289                                 if (!g_ascii_strcasecmp(nv->name, name)) {
290                                         g_free(filename);
291                                         g_free(corename);
292                                         return nv->val;
293                                 }
294                                 l=g_list_next(l);
295                         }
296                 }
297                 lpls=g_list_next(lpls);
298         }
299         g_free(filename);
300         g_free(corename);
301         return NULL;
302 }