5 #include <dirent.h> /* DIR, dirent */
6 #include <dlfcn.h> /* dlopen,dlclose,etc */
8 #include <evas_common.h>
9 #include <evas_private.h>
11 Evas_List *evas_modules = NULL;
12 static Evas_List *evas_module_paths = NULL;
15 _evas_module_path_append(Evas_Module_Type type, char *path, const char *subdir)
20 buf = evas_file_path_join(path, subdir);
22 if (evas_file_path_exists(buf))
24 mp = malloc(sizeof(Evas_Module_Path));
27 evas_module_paths = evas_list_append(evas_module_paths, mp);
34 /* this will alloc a list of paths to search for the modules */
35 /* by now these are: */
36 /* 1. ~/.evas/modules/ */
37 /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
38 /* 3. dladdr/evas/modules/ */
39 /* 4. PREFIX/evas/modules/ */
41 evas_module_paths_init(void)
46 Evas_List *paths = NULL;
48 /* 1. ~/.evas/modules/ */
49 prefix = getenv("HOME");
52 path = malloc(strlen(prefix) + 1 + strlen("/.evas/modules"));
57 strcat(path, "/.evas/modules");
58 if (evas_file_path_exists(path))
59 paths = evas_list_append(paths, path);
65 /* 2. $(EVAS_MODULE_DIR)/evas/modules/ */
66 prefix = getenv("EVAS_MODULES_DIR");
69 path = malloc(strlen(prefix) + 1 + strlen("/evas/modules"));
74 strcat(path, "/evas/modules");
75 if (evas_file_path_exists(path))
76 paths = evas_list_append(paths, path);
85 /* 3. libevas.so/../evas/modules/ */
86 if (dladdr(evas_module_paths_init, &evas_dl))
90 if (strrchr(evas_dl.dli_fname, '/'))
92 length = strlen(strrchr(evas_dl.dli_fname, '/'));
93 path = malloc(strlen(evas_dl.dli_fname) - length +
94 strlen("/evas/modules") + 1);
97 strncpy(path, evas_dl.dli_fname,
98 strlen(evas_dl.dli_fname) - length);
99 path[strlen(evas_dl.dli_fname) - length] = 0;
100 strcat(path, "/evas/modules");
101 if (evas_file_path_exists(path))
102 paths = evas_list_append(paths, path);
110 /* 4. PREFIX/evas/modules/ */
111 prefix = PACKAGE_LIB_DIR;
112 path = malloc(strlen(prefix) + 1 + strlen("/evas/modules"));
115 strcpy(path, prefix);
116 strcat(path, "/evas/modules");
117 if (evas_file_path_exists(path))
118 paths = evas_list_append(paths, path);
124 /* append all the module types subdirs */
127 /* here must be added all the types of modules and their subdirectory */
128 /* do this on a separate function */
130 _evas_module_path_append(EVAS_MODULE_TYPE_ENGINE, paths->data, "engines");
131 _evas_module_path_append(EVAS_MODULE_TYPE_IMAGE_LOADER, paths->data, "loaders");
132 _evas_module_path_append(EVAS_MODULE_TYPE_IMAGE_SAVER, paths->data, "savers");
133 _evas_module_path_append(EVAS_MODULE_TYPE_OBJECT, paths->data, "objects");
135 paths = evas_list_remove_list(paths, paths);
139 /* this will alloc an Evas_Module struct for each module
140 * it finds on the paths */
142 evas_module_init(void)
145 int new_id_engine = 1;
147 /* printf("[init modules]\n"); */
148 evas_module_paths_init();
149 for (l = evas_module_paths; l; l = l->next)
151 Evas_Module_Path *mp;
157 if (!(dir = opendir(mp->path))) break;
158 /* printf("[evas module] searching modules on %s\n", mp->path); */
159 while ((de = readdir(dir)))
163 if ((!strcmp(de->d_name, ".")) || (!strcmp(de->d_name, "..")))
165 buf = malloc(strlen(mp->path) + 1 + strlen(de->d_name) + 1);
166 sprintf(buf, "%s/%s", mp->path, de->d_name);
167 if (evas_file_path_is_dir(buf))
171 em = calloc(1, sizeof(Evas_Module));
173 em->name = strdup(de->d_name);
174 em->path = strdup(mp->path);
179 if (em->type == EVAS_MODULE_TYPE_ENGINE)
181 Evas_Module_Engine *eme;
183 eme = malloc(sizeof(Evas_Module_Engine));
186 eme->id = new_id_engine;
191 else if (em->type == EVAS_MODULE_TYPE_IMAGE_LOADER)
194 else if (em->type == EVAS_MODULE_TYPE_IMAGE_SAVER)
197 /* printf("[evas module] including module path %s/%s of type %d\n",em->path, em->name, em->type); */
198 evas_modules = evas_list_append(evas_modules, em);
207 evas_module_find_type(Evas_Module_Type type, const char *name)
211 for (l = evas_modules; l; l = l->next)
215 em = (Evas_Module*)l->data;
216 if ((type == em->type) && (!strcmp(name,em->name)))
218 if (evas_modules != l)
220 evas_modules = evas_list_promote_list(evas_modules, l);
229 evas_module_load(Evas_Module *em)
234 if (em->loaded) return 1;
236 /* printf("LOAD %s\n", em->name); */
237 #if defined(__CEGCC__) || defined(__MINGW32CE__)
239 case EVAS_MODULE_TYPE_IMAGE_SAVER:
240 snprintf(buf, sizeof(buf), "%s/%s/%s/saver_%s.dll", em->path, em->name, MODULE_ARCH, em->name);
242 case EVAS_MODULE_TYPE_IMAGE_LOADER:
243 snprintf(buf, sizeof(buf), "%s/%s/%s/loader_%s.dll", em->path, em->name, MODULE_ARCH, em->name);
245 case EVAS_MODULE_TYPE_ENGINE:
246 snprintf(buf, sizeof(buf), "%s/%s/%s/engine_%s.dll", em->path, em->name, MODULE_ARCH, em->name);
249 snprintf(buf, sizeof(buf), "%s/%s/%s/object_%s.dll", em->path, em->name, MODULE_ARCH, em->name);
252 snprintf(buf, sizeof(buf), "%s/%s/%s/module.dll", em->path, em->name, MODULE_ARCH);
254 snprintf(buf, sizeof(buf), "%s/%s/%s/module.so", em->path, em->name, MODULE_ARCH);
256 if (!evas_file_path_exists(buf))
258 printf("[evas module] error loading the module %s. It doesnt exists\n", buf);
262 handle = dlopen(buf, RTLD_LAZY);
266 em->func.open = dlsym(em->handle, "module_open");
267 em->func.close = dlsym(em->handle, "module_close");
268 em->api = dlsym(em->handle, "evas_modapi");
270 if ((!em->func.open) || (!em->api) || (!em->func.close))
273 if (em->api->version != EVAS_MODULE_API_VERSION)
275 printf("[evas module] error loading the modules %s. The version doesnt match\n", buf);
287 printf("[evas module] error loading the module %s. %s\n", buf, err);
291 em->func.open = NULL;
292 em->func.close = NULL;
299 evas_module_unload(Evas_Module *em)
309 em->func.open = NULL;
310 em->func.close = NULL;
316 evas_module_ref(Evas_Module *em)
319 /* printf("M: %s ref++ = %i\n", em->name, em->ref); */
323 evas_module_unref(Evas_Module *em)
326 /* printf("M: %s ref-- = %i\n", em->name, em->ref); */
329 static int use_count = 0;
332 evas_module_use(Evas_Module *em)
334 em->last_used = use_count;
338 evas_module_clean(void)
340 static int call_count = 0;
346 /* only clean modules every 256 calls */
348 if (call_count <= 256) return;
353 if (getenv("EVAS_NOCLEAN"))
359 if (noclean == 1) return;
361 /* disable module cleaning for now - may cause instability with some modules */
364 /* incriment use counter = 28bits */
366 if (use_count > 0x0fffffff) use_count = 0;
368 /* printf("CLEAN!\n"); */
369 /* go through all modules */
370 for (l = evas_modules; l; l = l->next)
373 /* printf("M %s %i %i\n", em->name, em->ref, em->loaded); */
374 /* if the module is refernced - skip */
375 if ((em->ref > 0) || (!em->loaded)) continue;
376 /* how many clean cycles ago was this module last used */
377 ago = use_count - em->last_used;
378 if (em->last_used > use_count) ago += 0x10000000;
379 /* if it was used last more than N clean cycles ago - unload */
382 /* printf(" UNLOAD %s\n", em->name); */
383 evas_module_unload(em);
388 /* will dlclose all the modules loaded and free all the structs */
390 evas_module_shutdown(void)
394 /* printf("[shutdown modules]\n"); */
397 em = (Evas_Module *)evas_modules->data;
398 evas_module_unload(em);
399 if (em->name) free(em->name);
400 if (em->path) free(em->path);
401 if (em->type == EVAS_MODULE_TYPE_ENGINE)
403 if (em->data) free(em->data);
405 else if (em->type == EVAS_MODULE_TYPE_IMAGE_LOADER)
408 else if (em->type == EVAS_MODULE_TYPE_IMAGE_SAVER)
411 free(evas_modules->data);
412 evas_modules = evas_list_remove_list(evas_modules, evas_modules);
414 while (evas_module_paths)
416 Evas_Module_Path *mp;
418 mp = evas_module_paths->data;
419 evas_module_paths = evas_list_remove_list(evas_module_paths, evas_module_paths);
426 _evas_module_engine_inherit(Evas_Func *funcs, char *name)
430 em = evas_module_find_type(EVAS_MODULE_TYPE_ENGINE, name);
433 if (evas_module_load(em))
435 /* FIXME: no way to unref */
438 *funcs = *((Evas_Func *)(em->functions));