Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / common tools sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "module_wrap.h"
27 : #include <gpac/network.h>
28 :
29 : #if defined(WIN32) || defined(_WIN32_WCE)
30 : #include <windows.h>
31 : #else
32 : #include <sys/stat.h>
33 : #include <dlfcn.h>
34 : #include <dirent.h>
35 : #endif
36 :
37 :
38 : /*delete all interfaces loaded on object*/
39 19180 : void gf_modules_free_module(ModuleInstance *inst)
40 : {
41 38360 : while (gf_list_count(inst->interfaces)) {
42 0 : void *objinterface = gf_list_get(inst->interfaces, 0);
43 0 : gf_list_rem(inst->interfaces, 0);
44 0 : inst->destroy_func(objinterface);
45 : }
46 :
47 : #ifdef WIN32
48 : if (inst->lib_handle) FreeLibrary((HMODULE)inst->lib_handle);
49 : #else
50 19180 : if (inst->lib_handle) dlclose(inst->lib_handle);
51 : #endif
52 19180 : if (inst->interfaces)
53 19180 : gf_list_del(inst->interfaces);
54 19180 : inst->interfaces = NULL;
55 :
56 19180 : if (inst->name && !inst->ifce_reg) {
57 19180 : gf_free(inst->name);
58 19180 : inst->name = NULL;
59 : }
60 :
61 19180 : if (inst->dir) {
62 19180 : gf_free(inst->dir);
63 19180 : inst->dir = NULL;
64 : }
65 19180 : gf_free(inst);
66 19180 : }
67 :
68 :
69 6061 : Bool gf_modules_load_library(ModuleInstance *inst)
70 : {
71 : #if defined(GPAC_MP4BOX_MINI)
72 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load dynamic module %s from static build.\n", (inst && inst->name) ? inst->name : ""));
73 : return GF_FALSE;
74 : #endif
75 :
76 : #ifdef WIN32
77 : DWORD res;
78 :
79 : #ifdef _WIN32_WCE
80 : char s_path[GF_MAX_PATH];
81 : unsigned short path[GF_MAX_PATH];
82 : #else
83 : char path[GF_MAX_PATH];
84 : #endif
85 :
86 : #else
87 : char path[GF_MAX_PATH];
88 : s32 _flags;
89 : const char * error;
90 : #endif
91 :
92 6061 : if (inst->lib_handle) return GF_TRUE;
93 :
94 4528 : if (inst->ifce_reg) {
95 0 : inst->query_func = (QueryInterfaces) inst->ifce_reg->QueryInterfaces;
96 0 : inst->load_func = (LoadInterface) inst->ifce_reg->LoadInterface;
97 0 : inst->destroy_func = (ShutdownInterface) inst->ifce_reg->ShutdownInterface;
98 0 : return GF_TRUE;
99 : }
100 :
101 4528 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Load module file %s\n", inst->name));
102 :
103 : #if _WIN32_WINNT >= 0x0502
104 : SetDllDirectory(inst->dir);
105 : #endif
106 :
107 : #ifdef _WIN32_WCE
108 : sprintf(s_path, "%s%c%s", inst->dir, GF_PATH_SEPARATOR, inst->name);
109 : CE_CharToWide(s_path, path);
110 : #else
111 4528 : sprintf(path, "%s%c%s", inst->dir, GF_PATH_SEPARATOR, inst->name);
112 : #endif
113 :
114 : #ifdef WIN32
115 : inst->lib_handle = LoadLibrary(path);
116 : if (!inst->lib_handle) {
117 : res = GetLastError();
118 : #ifdef _WIN32_WCE
119 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load module file %s: error %d\n", s_path, res));
120 : #else
121 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load module file %s: error %d\n", path, res));
122 : #endif
123 : return GF_FALSE;
124 : }
125 : #if defined(_WIN32_WCE)
126 : inst->query_func = (QueryInterfaces) GetProcAddress(inst->lib_handle, _T("QueryInterfaces"));
127 : inst->load_func = (LoadInterface) GetProcAddress(inst->lib_handle, _T("LoadInterface"));
128 : inst->destroy_func = (ShutdownInterface) GetProcAddress(inst->lib_handle, _T("ShutdownInterface"));
129 : inst->filterreg_func = (ShutdownInterface) GetProcAddress(inst->lib_handle, _T("RegisterFilter"));
130 : #else
131 : inst->query_func = (QueryInterfaces) GetProcAddress((HMODULE)inst->lib_handle, "QueryInterfaces");
132 : inst->load_func = (LoadInterface) GetProcAddress((HMODULE)inst->lib_handle, "LoadInterface");
133 : inst->destroy_func = (ShutdownInterface) GetProcAddress((HMODULE)inst->lib_handle, "ShutdownInterface");
134 : inst->filterreg_func = (LoadFilterRegister) GetProcAddress((HMODULE)inst->lib_handle, "RegisterFilter");
135 : #endif
136 :
137 : #else
138 :
139 : #ifdef RTLD_GLOBAL
140 : _flags =RTLD_LAZY | RTLD_GLOBAL;
141 : #else
142 : _flags =RTLD_LAZY;
143 : #endif
144 4528 : inst->lib_handle = dlopen(path, _flags);
145 4528 : if (!inst->lib_handle) {
146 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load module file %s, error is %s\n", path, dlerror()));
147 : return 0;
148 : }
149 4528 : error = dlerror(); /* Clear any existing error */
150 4528 : if (error)
151 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[Core] Cleaning up previous dlerror %s\n", error));
152 4528 : inst->query_func = (QueryInterfaces) dlsym(inst->lib_handle, "QueryInterfaces");
153 4528 : inst->load_func = (LoadInterface) dlsym(inst->lib_handle, "LoadInterface");
154 4528 : inst->destroy_func = (ShutdownInterface) dlsym(inst->lib_handle, "ShutdownInterface");
155 4528 : inst->filterreg_func = (LoadFilterRegister) dlsym(inst->lib_handle, "RegisterFilter");
156 : #endif
157 4528 : if (!inst->filterreg_func && (!inst->load_func || !inst->query_func || !inst->destroy_func) ) {
158 :
159 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Invalid module file %s, missing %s function\n", inst->name, !inst->query_func ? "QueryInterface" : !inst->load_func ? "LoadInterface" : "ShutdownInterface"));
160 : return GF_TRUE;
161 : }
162 :
163 4528 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Load module file %s OK\n", inst->name));
164 : return GF_TRUE;
165 : }
166 :
167 6058 : void gf_modules_unload_library(ModuleInstance *inst)
168 : {
169 6058 : if (!inst->lib_handle || gf_list_count(inst->interfaces)) return;
170 : /*module unloading is disabled*/
171 6058 : if (inst->plugman->no_unload)
172 : return;
173 :
174 : /*filters are not unloaded*/
175 0 : if (inst->filterreg_func)
176 : return;
177 :
178 : #ifdef WIN32
179 : if (strcmp(inst->name, "gf_ohevcdec.dll"))
180 : FreeLibrary((HMODULE)inst->lib_handle);
181 : #else
182 0 : dlclose(inst->lib_handle);
183 : #endif
184 0 : inst->lib_handle = NULL;
185 0 : inst->load_func = NULL;
186 0 : inst->destroy_func = NULL;
187 0 : inst->query_func = NULL;
188 : }
189 :
190 :
191 19187 : static Bool enum_modules(void *cbck, char *item_name, char *item_path, GF_FileEnumInfo *file_info)
192 : {
193 : ModuleInstance *inst;
194 : char *sep;
195 : #if CHECK_MODULE
196 : QueryInterface query_func;
197 : LoadInterface load_func;
198 : ShutdownInterface del_func;
199 : LoadFilterRegister filterreg_func;
200 : #ifdef WIN32
201 : HMODULE ModuleLib;
202 : #else
203 : void *ModuleLib;
204 : s32 _flags;
205 : #endif
206 :
207 : #endif
208 :
209 : GF_ModuleManager *pm = (GF_ModuleManager*)cbck;
210 :
211 19187 : if (strstr(item_name, "nposmozilla")) return GF_FALSE;
212 19187 : if (strncmp(item_name, "gf_", 3) && strncmp(item_name, "gm_", 3) && strncmp(item_name, "libgm_", 6)) return GF_FALSE;
213 19187 : if (gf_module_is_loaded(pm, item_name) ) return GF_FALSE;
214 :
215 : #if CHECK_MODULE
216 :
217 : #ifdef WIN32
218 : ModuleLib = LoadLibrary(item_path);
219 : if (!ModuleLib) {
220 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load module file %s\n", item_name));
221 : return GF_FALSE;
222 : }
223 :
224 : #ifdef _WIN32_WCE
225 : query_func = (QueryInterface) GetProcAddress(ModuleLib, _T("QueryInterface"));
226 : load_func = (LoadInterface) GetProcAddress(ModuleLib, _T("LoadInterface"));
227 : del_func = (ShutdownInterface) GetProcAddress(ModuleLib, _T("ShutdownInterface"));
228 : filterreg_func = (LoadFilterRegister) GetProcAddress(ModuleLib, _T("RegisterFilter"));
229 :
230 : #else
231 : query_func = (QueryInterface) GetProcAddress(ModuleLib, "QueryInterface");
232 : load_func = (LoadInterface) GetProcAddress(ModuleLib, "LoadInterface");
233 : del_func = (ShutdownInterface) GetProcAddress(ModuleLib, "ShutdownInterface");
234 : filterreg_func = (LoadFilterRegister) GetProcAddress(ModuleLib, "RegisterFilter");
235 : #endif
236 : FreeLibrary(ModuleLib);
237 :
238 : #else
239 :
240 : #ifdef RTLD_GLOBAL
241 : _flags =RTLD_LAZY | RTLD_GLOBAL;
242 : #else
243 : _flags =RTLD_LAZY;
244 : #endif
245 :
246 : ModuleLib = dlopen(item_name, _flags);
247 : if (!ModuleLib) {
248 : GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot load module file %s, error is %s\n", item_name, dlerror()));
249 : goto next;
250 : }
251 :
252 : query_func = (QueryInterface) dlsym(ModuleLib, "QueryInterface");
253 : load_func = (LoadInterface) dlsym(ModuleLib, "LoadInterface");
254 : del_func = (ShutdownInterface) dlsym(ModuleLib, "ShutdownInterface");
255 : filterreg_func = (LoadFilterRegister) dlsym(ModuleLib, "RegisterFilter");
256 : dlclose(ModuleLib);
257 : #endif
258 :
259 : if (!filterreg_func && (!load_func || !query_func || !del_func) ) {
260 : GF_LOG(GF_LOG_WARNING, GF_LOG_CORE,
261 : ("[Core] Could not find some signatures in module %s: QueryInterface=%p, LoadInterface=%p, ShutdownInterface=%p\n",
262 : item_name, load_func, query_func, del_func));
263 : return GF_FALSE;
264 : }
265 : #endif
266 :
267 19187 : GF_SAFEALLOC(inst, ModuleInstance);
268 19187 : if (!inst) return GF_FALSE;
269 19187 : inst->interfaces = gf_list_new();
270 19187 : if (!inst->interfaces) {
271 0 : gf_free(inst);
272 0 : return GF_FALSE;
273 : }
274 19187 : inst->plugman = pm;
275 19187 : inst->name = gf_strdup(item_name);
276 19187 : inst->dir = gf_strdup(item_path);
277 :
278 19187 : sep = strrchr(inst->dir, '/');
279 19187 : if (!sep) sep = strrchr(inst->dir, '\\');
280 19187 : if (sep) sep[1] = 0;
281 :
282 19187 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Added module %s.\n", inst->name));
283 19187 : gf_list_add(pm->plug_list, inst);
284 19187 : return GF_FALSE;
285 : }
286 :
287 2741 : static void load_static_modules(GF_ModuleManager *pm)
288 : {
289 : ModuleInstance *inst;
290 : u32 i, count;
291 2741 : count = gf_list_count(pm->plugin_registry);
292 2741 : for (i=0; i<count; i++) {
293 0 : GF_InterfaceRegister *ifce_reg = (GF_InterfaceRegister*)gf_list_get(pm->plugin_registry, i);
294 0 : if (gf_module_is_loaded(pm, (char *) ifce_reg->name) ) continue;
295 :
296 0 : GF_SAFEALLOC(inst, ModuleInstance);
297 0 : if (!inst) continue;
298 0 : inst->interfaces = gf_list_new();
299 0 : if (!inst->interfaces) {
300 0 : gf_free(inst);
301 0 : continue;
302 : }
303 0 : inst->plugman = pm;
304 0 : inst->name = (char *) ifce_reg->name;
305 0 : inst->ifce_reg = ifce_reg;
306 0 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Core] Added static module %s.\n", inst->name));
307 0 : gf_list_add(pm->plug_list, inst);
308 : }
309 2741 : }
310 :
311 : /*refresh modules - note we don't check for deleted modules but since we've open them the OS should forbid delete*/
312 : GF_EXPORT
313 2741 : u32 gf_modules_refresh(GF_ModuleManager *pm)
314 : {
315 : u32 i;
316 2741 : if (!pm) return 0;
317 :
318 : /*load all static modules*/
319 2741 : load_static_modules(pm);
320 :
321 5482 : for (i =0; i < pm->num_dirs; i++) {
322 2741 : GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("Refreshing list of modules in directory %s\n", pm->dirs[i]));
323 : #ifdef WIN32
324 : gf_enum_directory(pm->dirs[i], GF_FALSE, enum_modules, pm, ".dll");
325 : #elif defined(__APPLE__)
326 : #if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR)
327 : /*we are in static build for modules by default*/
328 : #else
329 : gf_enum_directory(pm->dirs[i], 0, enum_modules, pm, ".dylib");
330 : #endif
331 : #else
332 :
333 : #if defined(GPAC_CONFIG_WIN32)
334 : gf_enum_directory(pm->dirs[i], 0, enum_modules, pm, ".dll");
335 : #else
336 2741 : gf_enum_directory(pm->dirs[i], 0, enum_modules, pm, ".so");
337 : #endif
338 :
339 : #endif
340 : }
341 :
342 2741 : return gf_list_count(pm->plug_list);
343 : }
|