7 #include <evas_common.h>
8 #include <evas_private.h>
9 #include <evas_module.h>
12 static Eina_Hash *evas_modules[4] = {
19 static Eina_List *eina_evas_modules = NULL;
20 static Eina_List *evas_module_paths = NULL;
21 static Eina_Array *evas_engines = NULL;
24 _evas_module_append(Eina_List *list, char *path)
28 if (evas_file_path_exists(path))
29 list = eina_list_append(list, path);
36 /* this will alloc a list of paths to search for the modules */
37 /* by now these are: */
38 /* 1. ~/.evas/modules/ */
39 /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
40 /* 3. dladdr/evas/modules/ */
41 /* 4. PREFIX/evas/modules/ */
43 evas_module_paths_init(void)
47 /* 1. ~/.evas/modules/ */
48 path = eina_module_environment_path_get("HOME", "/.evas/modules");
49 evas_module_paths = _evas_module_append(evas_module_paths, path);
51 /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
52 path = eina_module_environment_path_get("EVAS_MODULES_DIR", "/evas/modules");
53 if (eina_list_search_unsorted(evas_module_paths, (Eina_Compare_Cb) strcmp, path))
56 evas_module_paths = _evas_module_append(evas_module_paths, path);
58 /* 3. libevas.so/../evas/modules/ */
59 path = eina_module_symbol_path_get(evas_module_paths_init, "/evas/modules");
60 if (eina_list_search_unsorted(evas_module_paths, (Eina_Compare_Cb) strcmp, path))
63 evas_module_paths = _evas_module_append(evas_module_paths, path);
65 /* 4. PREFIX/evas/modules/ */
67 path = PACKAGE_LIB_DIR "/evas/modules";
68 if (!eina_list_search_unsorted(evas_module_paths, (Eina_Compare_Cb) strcmp, path))
72 evas_module_paths = _evas_module_append(evas_module_paths, path);
77 #define EVAS_EINA_STATIC_MODULE_DEFINE(Tn, Name) \
78 Eina_Bool evas_##Tn##_##Name##_init(void); \
79 void evas_##Tn##_##Name##_shutdown(void);
81 #define EVAS_EINA_STATIC_MODULE_USE(Tn, Name) \
82 { evas_##Tn##_##Name##_init, evas_##Tn##_##Name##_shutdown }
84 EVAS_EINA_STATIC_MODULE_DEFINE(engine, buffer);
85 EVAS_EINA_STATIC_MODULE_DEFINE(engine, direct3d);
86 EVAS_EINA_STATIC_MODULE_DEFINE(engine, directfb);
87 EVAS_EINA_STATIC_MODULE_DEFINE(engine, fb);
88 EVAS_EINA_STATIC_MODULE_DEFINE(engine, gl_x11);
89 EVAS_EINA_STATIC_MODULE_DEFINE(engine, gl_sdl);
90 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16);
91 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_ddraw);
92 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_sdl);
93 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_wince);
94 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_16_x11);
95 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8);
96 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_8_x11);
97 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_ddraw);
98 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_gdi);
99 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_generic);
100 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_sdl);
101 EVAS_EINA_STATIC_MODULE_DEFINE(engine, software_x11);
102 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp);
103 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, edb);
104 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet);
105 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, generic);
106 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, gif);
107 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico);
108 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jpeg);
109 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, pmaps);
110 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, png);
111 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, psd);
112 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, svg);
113 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga);
114 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tiff);
115 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp);
116 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, xpm);
117 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb);
118 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
119 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
120 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png);
121 EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, tiff);
123 static const struct {
124 Eina_Bool (*init)(void);
125 void (*shutdown)(void);
126 } evas_static_module[] = {
127 #ifdef EVAS_STATIC_BUILD_BUFFER
128 EVAS_EINA_STATIC_MODULE_USE(engine, buffer),
130 #ifdef EVAS_STATIC_BUILD_DIRECT3D
131 EVAS_EINA_STATIC_MODULE_USE(engine, direct3d),
133 #ifdef EVAS_STATIC_BUILD_DIRECTFB
134 EVAS_EINA_STATIC_MODULE_USE(engine, directfb),
136 #ifdef EVAS_STATIC_BUILD_FB
137 EVAS_EINA_STATIC_MODULE_USE(engine, fb),
139 #ifdef EVAS_STATIC_BUILD_GL_X11
140 EVAS_EINA_STATIC_MODULE_USE(engine, gl_x11),
142 #ifdef EVAS_STATIC_BUILD_GL_SDL
143 EVAS_EINA_STATIC_MODULE_USE(engine, gl_sdl),
145 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16
146 EVAS_EINA_STATIC_MODULE_USE(engine, software_16),
148 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_DDRAW
149 EVAS_EINA_STATIC_MODULE_USE(engine, software_16_ddraw),
151 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_SDL
152 EVAS_EINA_STATIC_MODULE_USE(engine, software_16_sdl),
154 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_WINCE
155 EVAS_EINA_STATIC_MODULE_USE(engine, software_16_wince),
157 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_X11
158 EVAS_EINA_STATIC_MODULE_USE(engine, software_16_x11),
160 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_DDRAW
161 EVAS_EINA_STATIC_MODULE_USE(engine, software_ddraw),
163 #ifdef EVAS_STATIC_BUILD_SOFTWARE_16_GDI
164 EVAS_EINA_STATIC_MODULE_USE(engine, software_gdi),
166 #ifdef EVAS_STATIC_BUILD_SOFTWARE_8
167 EVAS_EINA_STATIC_MODULE_USE(engine, software_8),
169 #ifdef EVAS_STATIC_BUILD_SOFTWARE_8_X11
170 EVAS_EINA_STATIC_MODULE_USE(engine, software_8_x11),
172 #ifdef EVAS_STATIC_BUILD_SOFTWARE_GENERIC
173 EVAS_EINA_STATIC_MODULE_USE(engine, software_generic),
175 #ifdef EVAS_STATIC_BUILD_SOFTWARE_SDL
176 EVAS_EINA_STATIC_MODULE_USE(engine, software_sdl),
178 #ifdef EVAS_STATIC_BUILD_SOFTWARE_X11
179 EVAS_EINA_STATIC_MODULE_USE(engine, software_x11),
181 #ifdef EVAS_STATIC_BUILD_BMP
182 EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp),
184 #ifdef EVAS_STATIC_BUILD_EDB
185 EVAS_EINA_STATIC_MODULE_USE(image_loader, edb),
187 #ifdef EVAS_STATIC_BUILD_EET
188 EVAS_EINA_STATIC_MODULE_USE(image_loader, eet),
190 #ifdef EVAS_STATIC_BUILD_GENERIC
191 EVAS_EINA_STATIC_MODULE_USE(image_loader, generic),
193 #ifdef EVAS_STATIC_BUILD_GIF
194 EVAS_EINA_STATIC_MODULE_USE(image_loader, gif),
196 #ifdef EVAS_STATIC_BUILD_ICO
197 EVAS_EINA_STATIC_MODULE_USE(image_loader, ico),
199 #ifdef EVAS_STATIC_BUILD_JPEG
200 EVAS_EINA_STATIC_MODULE_USE(image_loader, jpeg),
202 #ifdef EVAS_STATIC_BUILD_PMAPS
203 EVAS_EINA_STATIC_MODULE_USE(image_loader, pmaps),
205 #ifdef EVAS_STATIC_BUILD_PNG
206 EVAS_EINA_STATIC_MODULE_USE(image_loader, png),
208 #ifdef EVAS_STATIC_BUILD_PSD
209 EVAS_EINA_STATIC_MODULE_USE(image_loader, psd),
211 #ifdef EVAS_STATIC_BUILD_SVG
212 EVAS_EINA_STATIC_MODULE_USE(image_loader, svg),
214 #ifdef EVAS_STATIC_BUILD_TGA
215 EVAS_EINA_STATIC_MODULE_USE(image_loader, tga),
217 #ifdef EVAS_STATIC_BUILD_TIFF
218 EVAS_EINA_STATIC_MODULE_USE(image_loader, tiff),
220 #ifdef EVAS_STATIC_BUILD_WBMP
221 EVAS_EINA_STATIC_MODULE_USE(image_loader, wbmp),
223 #ifdef EVAS_STATIC_BUILD_XPM
224 EVAS_EINA_STATIC_MODULE_USE(image_loader, xpm),
226 #ifdef EVAS_STATIC_BUILD_EDB
227 EVAS_EINA_STATIC_MODULE_USE(image_saver, edb),
229 #ifdef EVAS_STATIC_BUILD_EET
230 EVAS_EINA_STATIC_MODULE_USE(image_saver, eet),
232 #if defined (EVAS_BUILD_SAVER_JPEG) && defined (EVAS_STATIC_BUILD_JPEG)
233 EVAS_EINA_STATIC_MODULE_USE(image_saver, jpeg),
235 #ifdef EVAS_STATIC_BUILD_PNG
236 EVAS_EINA_STATIC_MODULE_USE(image_saver, png),
238 #ifdef EVAS_STATIC_BUILD_TIFF
239 EVAS_EINA_STATIC_MODULE_USE(image_saver, tiff),
244 /* this will alloc an Evas_Module struct for each module
245 * it finds on the paths */
247 evas_module_init(void)
251 evas_module_paths_init();
253 evas_modules[EVAS_MODULE_TYPE_ENGINE] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
254 evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
255 evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
256 evas_modules[EVAS_MODULE_TYPE_OBJECT] = eina_hash_string_small_new(/* FIXME: Add a function to cleanup stuff. */ NULL);
258 evas_engines = eina_array_new(4);
260 for (i = 0; evas_static_module[i].init; ++i)
261 evas_static_module[i].init();
265 evas_module_register(const Evas_Module_Api *module, Evas_Module_Type type)
269 if ((unsigned int)type > 3) return EINA_FALSE;
270 if (!module) return EINA_FALSE;
271 if (module->version != EVAS_MODULE_API_VERSION) return EINA_FALSE;
273 em = eina_hash_find(evas_modules[type], module->name);
274 if (em) return EINA_FALSE;
276 em = calloc(1, sizeof (Evas_Module));
277 if (!em) return EINA_FALSE;
279 em->definition = module;
281 if (type == EVAS_MODULE_TYPE_ENGINE)
283 eina_array_push(evas_engines, em);
284 em->id_engine = eina_array_count_get(evas_engines);
287 eina_hash_direct_add(evas_modules[type], module->name, em);
293 evas_module_unregister(const Evas_Module_Api *module, Evas_Module_Type type)
297 if ((unsigned int)type > 3) return EINA_FALSE;
298 if (!module) return EINA_FALSE;
300 em = eina_hash_find(evas_modules[type], module->name);
301 if (!em || em->definition != module) return EINA_FALSE;
303 if (type == EVAS_MODULE_TYPE_ENGINE)
304 eina_array_data_set(evas_engines, em->id_engine, NULL);
306 eina_hash_del(evas_modules[type], module->name, em);
312 #if defined(__CEGCC__) || defined(__MINGW32CE__)
313 # define EVAS_MODULE_NAME_IMAGE_SAVER "saver_%s.dll"
314 # define EVAS_MODULE_NAME_IMAGE_LOADER "loader_%s.dll"
315 # define EVAS_MODULE_NAME_ENGINE "engine_%s.dll"
316 # define EVAS_MODULE_NAME_OBJECT "object_%s.dll"
318 # define EVAS_MODULE_NAME_IMAGE_SAVER "module.dll"
319 # define EVAS_MODULE_NAME_IMAGE_LOADER "module.dll"
320 # define EVAS_MODULE_NAME_ENGINE "module.dll"
321 # define EVAS_MODULE_NAME_OBJECT "module.dll"
323 # define EVAS_MODULE_NAME_IMAGE_SAVER "module.so"
324 # define EVAS_MODULE_NAME_IMAGE_LOADER "module.so"
325 # define EVAS_MODULE_NAME_ENGINE "module.so"
326 # define EVAS_MODULE_NAME_OBJECT "module.so"
330 evas_module_find_type(Evas_Module_Type type, const char *name)
333 const char *format = NULL;
339 if ((unsigned int)type > 3) return NULL;
341 em = eina_hash_find(evas_modules[type], name);
344 EINA_LIST_FOREACH(evas_module_paths, l, path)
348 case EVAS_MODULE_TYPE_ENGINE: format = "%s/engines/%s/%s/" EVAS_MODULE_NAME_ENGINE; break;
349 case EVAS_MODULE_TYPE_IMAGE_LOADER: format = "%s/loaders/%s/%s/" EVAS_MODULE_NAME_IMAGE_LOADER; break;
350 case EVAS_MODULE_TYPE_IMAGE_SAVER: format = "%s/savers/%s/%s/" EVAS_MODULE_NAME_IMAGE_SAVER; break;
351 case EVAS_MODULE_TYPE_OBJECT: format = "%s/object/%s/%s/" EVAS_MODULE_NAME_OBJECT; break;
354 snprintf(buffer, sizeof (buffer), format, path, name, MODULE_ARCH, name);
355 if (!evas_file_path_is_file(buffer)) continue;
357 en = eina_module_new(buffer);
360 if (!eina_module_load(en))
362 eina_module_free(en);
366 em = eina_hash_find(evas_modules[type], name);
369 eina_evas_modules = eina_list_append(eina_evas_modules, en);
373 eina_module_free(en);
380 evas_module_engine_get(int render_method)
382 if ((render_method <= 0) ||
383 ((unsigned int)render_method > eina_array_count_get(evas_engines)))
385 return eina_array_data_get(evas_engines, render_method - 1);
389 evas_module_foreach_image_loader(Eina_Hash_Foreach cb, const void *fdata)
391 eina_hash_foreach(evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER], cb, fdata);
395 evas_module_load(Evas_Module *em)
397 if (em->loaded) return 1;
398 if (!em->definition) return 0;
400 if (!em->definition->func.open(em)) return 0;
403 #ifdef BUILD_ASYNC_PRELOAD
410 evas_module_unload(Evas_Module *em)
417 // for now lets not unload modules - they may still be in use.
418 // em->definition->func.close(em);
421 #ifdef BUILD_ASYNC_PRELOAD
427 evas_module_ref(Evas_Module *em)
429 #ifdef BUILD_ASYNC_PRELOAD
433 #ifdef BUILD_ASYNC_PRELOAD
439 evas_module_unref(Evas_Module *em)
441 #ifdef BUILD_ASYNC_PRELOAD
445 #ifdef BUILD_ASYNC_PRELOAD
450 static int use_count = 0;
453 evas_module_use(Evas_Module *em)
455 em->last_used = use_count;
459 evas_module_clean(void)
461 static int call_count = 0;
465 /* Evas_Module *em; */
467 /* only clean modules every 256 calls */
469 if (call_count <= 256) return;
474 if (getenv("EVAS_NOCLEAN"))
479 if (noclean == 1) return;
481 /* disable module cleaning for now - may cause instability with some modules */
484 /* FIXME: Don't know what it is supposed to do. */
485 /* /\* incriment use counter = 28bits *\/ */
487 /* if (use_count > 0x0fffffff) use_count = 0; */
489 /* /\* printf("CLEAN!\n"); *\/ */
490 /* /\* go through all modules *\/ */
491 /* EINA_LIST_FOREACH(evas_modules, l, em) */
493 /* /\* printf("M %s %i %i\n", em->name, em->ref, em->loaded); *\/ */
494 /* /\* if the module is refernced - skip *\/ */
495 /* if ((em->ref > 0) || (!em->loaded)) continue; */
496 /* /\* how many clean cycles ago was this module last used *\/ */
497 /* ago = use_count - em->last_used; */
498 /* if (em->last_used > use_count) ago += 0x10000000; */
499 /* /\* if it was used last more than N clean cycles ago - unload *\/ */
502 /* /\* printf(" UNLOAD %s\n", em->name); *\/ */
503 /* evas_module_unload(em); */
508 /* will dlclose all the modules loaded and free all the structs */
510 evas_module_shutdown(void)
516 for (i = 0; evas_static_module[i].shutdown; ++i)
517 evas_static_module[i].shutdown();
519 EINA_LIST_FREE(eina_evas_modules, en)
520 eina_module_free(en);
522 eina_hash_free(evas_modules[EVAS_MODULE_TYPE_ENGINE]);
523 evas_modules[EVAS_MODULE_TYPE_ENGINE] = NULL;
524 eina_hash_free(evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER]);
525 evas_modules[EVAS_MODULE_TYPE_IMAGE_LOADER] = NULL;
526 eina_hash_free(evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER]);
527 evas_modules[EVAS_MODULE_TYPE_IMAGE_SAVER] = NULL;
528 eina_hash_free(evas_modules[EVAS_MODULE_TYPE_OBJECT]);
529 evas_modules[EVAS_MODULE_TYPE_OBJECT] = NULL;
531 EINA_LIST_FREE(evas_module_paths, path)
534 eina_array_free(evas_engines);
539 _evas_module_engine_inherit(Evas_Func *funcs, char *name)
543 em = evas_module_find_type(EVAS_MODULE_TYPE_ENGINE, name);
546 if (evas_module_load(em))
548 /* FIXME: no way to unref */
551 *funcs = *((Evas_Func *)(em->functions));