1 /*
2 MPEG Maaate: An Australian MPEG audio analysis toolkit
3 Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
4 (CSIRO), Australia.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "plugins.H"
27
28 #include <dirent.h>
29
30 #if (defined (WIN32) || (_WIN32))
31 #define DIRSEP "\\"
32 #define PATHSEP ";"
33 #else
34 #include <dlfcn.h>
35 #define DIRSEP '/'
36 #define PATHSEP ":"
37 #endif
38
39
40 #include <cstdlib>
41 #include <sys/types.h>
42
43 typedef list<Module> * (*loadFunc) ();
44 typedef void (*unloadFunc) ();
45
46 CSAPI_TIER2
PluginLibrary(string filename)47 PluginLibrary::PluginLibrary (string filename) {
48 list<Module> * tmp;
49 // remember filename
50 name = filename;
51
52 // open the library and get a handle to it
53 #if (defined (WIN32) || (_WIN32))
54 hLib = LoadLibrary(filename.c_str());
55 if (!hLib) {
56 cerr << "MaaateA: error opening " << filename << ": " << endl;
57 return;
58 }
59 #else
60 plib = dlopen (filename.c_str(), RTLD_NOW);
61 if (!plib) {
62 cerr << "MaaateA: error opening " << filename << ": " << dlerror() << endl;
63 return;
64 }
65 #endif
66
67 // get the function to load the modules of the library and call it
68 // returning a list of modules; the initialisation functions are
69 // also called during construction of modules
70 loadFunc loadModules;
71 #if (defined (WIN32) || (_WIN32))
72 loadModules = (loadFunc)GetProcAddress(hLib, "loadModules");
73 if (!loadModules) {
74 cerr << "MaaateA: error reading symbol from " << filename << ": " << endl;
75 return;
76 }
77 #else
78 loadModules = (loadFunc) dlsym (plib, "loadModules");
79 if (!loadModules) {
80 cerr << "MaaateA: error reading symbol from " << filename << ": " << endl;
81 cerr << dlerror () << endl;
82 return;
83 }
84 #endif
85 tmp = loadModules();
86 modList = *tmp;
87
88 // set the plib/hLib member of each module that was loaded
89 list<Module>::iterator iter;
90 for (iter = modList.begin(); iter != modList.end(); ++iter) {
91 (*iter).plib = this;
92 }
93 }
94
95 CSAPI_TIER2
~PluginLibrary()96 PluginLibrary::~PluginLibrary() {
97 // cleanup the modules
98 unloadFunc unloadModules;
99
100 #if (defined (WIN32) || (_WIN32))
101 unloadModules = (unloadFunc)GetProcAddress((HMODULE)hLib, "unloadModules");
102 unloadModules();
103
104 // close the library
105 FreeLibrary((HMODULE)hLib);
106 #else
107 unloadModules = (unloadFunc) dlsym (plib, "unloadModules");
108 unloadModules();
109
110 // close the library
111 dlclose(plib);
112 #endif
113 }
114
115 CSAPI_TIER2 void
AddStaticModules()116 Plugins::AddStaticModules () {
117 }
118
119 CSAPI_TIER2 bool
AddLibrary(string filename)120 Plugins::AddLibrary (string filename) {
121 // find library either at given place or
122 // in MAAATE_PATH environment variable path or
123 // in standard PACKAGE_PLUGIN_DIR path or
124 // in standard /usr/local/lib
125 struct stat *buf = (struct stat *) malloc (sizeof(struct stat));
126 string filepath = string(filename);
127
128 // Check that filename ends in ".so"
129 // string::size_type pos = filename.rfind ('.');
130 string::size_type pos = filename.rfind ('.');
131 if (pos == string::npos) {
132 cerr << "MaaateA: warning " << filename << " not opened" << endl;
133 free(buf);
134 return false;
135 }
136 string extension(filename, pos, string::npos);
137 #if (defined (WIN32) || (_WIN32))
138 if (extension != ".dll") {
139 cerr << "MaaateA: warning " << filename << " not opened" << endl;
140 free(buf);
141 return false;
142 }
143
144 #else
145 if (extension != ".so") {
146 cerr << "MaaateA: warning " << filename << " not opened" << endl;
147 free(buf);
148 return false;
149 }
150 #endif
151
152
153 if (stat(filename.c_str(), buf) != 0) {
154 // some error occured when opening file - presume file doesn't exist
155 // => try with different paths
156 char * mpath = getenv("MAAATE_PATH");
157 string crudpath;
158 if (mpath != NULL && strlen(mpath) != 0)
159 {
160 crudpath.append(mpath);
161 crudpath.append(PATHSEP);
162 }
163
164 crudpath.append(PACKAGE_PLUGIN_DIR);
165 #if (defined (WIN32) || (_WIN32))
166 #ifdef _DEBUG
167 crudpath.append(";.\\debug");
168 #else
169 crudpath.append(";.\\release");
170 #endif
171 #else
172 crudpath.append(":/usr/local/lib/");
173 #endif
174
175 // go through colon-separated directory list and try library in each
176 // always cutting out the first name
177 bool found = false;
178 string tmpdir;
179 string::size_type pos = 0;
180 while ((pos=crudpath.find(PATHSEP, pos)) != string::npos) {
181 tmpdir = string(crudpath, (string::size_type) 0, pos);
182 if (stat((tmpdir+DIRSEP+filename).c_str(), buf) == 0) {
183 filepath = (tmpdir+DIRSEP+filename);
184 found = true;
185 break;
186 }
187 crudpath.erase ((string::size_type) 0, pos+1);
188 }
189 if (!found) {
190 // try last dirname
191 if (stat((crudpath+DIRSEP+filename).c_str(), buf) == 0) {
192 filepath = (crudpath)+DIRSEP+filename;
193 } else {
194 free(buf);
195 return false;
196 }
197 }
198 }
199
200 PluginLibrary * pl = new PluginLibrary (filepath);
201 list<Module> * ml = pl->Modules();
202
203 list<Module>::iterator iter;
204 for (iter = ml->begin(); iter != ml->end(); ++iter) {
205 AddModule (&(*iter));
206 }
207 free(buf);
208 return true;
209 }
210
211 CSAPI_TIER2 void
AddLibraries(string dirname)212 Plugins::AddLibraries (string dirname) {
213 DIR * dir;
214 struct dirent * direntity;
215
216 dir = opendir(dirname.c_str());
217 if (dir == NULL) return;
218
219 /* read directory entries one at a time */
220 while ((direntity=readdir(dir)) != NULL) {
221 AddLibrary(direntity->d_name);
222 }
223 }
224
225 CSAPI_TIER2 void
AddLibrariesPath(string pathlist)226 Plugins::AddLibrariesPath (string pathlist) {
227 string crudpath = string(pathlist);
228 string tmpdir;
229 string::size_type pos = 0;
230
231 // go through colon-separated directory list and add libraries from there
232 // always cutting out the first name
233 while ((pos=crudpath.find(':', pos)) != string::npos) {
234 tmpdir = string(crudpath, (string::size_type) 0, pos);
235 AddLibraries (crudpath);
236 crudpath.erase ((string::size_type) 0, pos+1);
237 }
238 // add last dirname
239 AddLibraries (crudpath);
240
241 }
242
243 CSAPI_TIER2 void
AddLibrariesMaaatePath()244 Plugins::AddLibrariesMaaatePath () {
245 AddStaticModules ();
246
247 char * mpath = getenv("MAAATE_PATH");
248 string crudpath = string();
249 if (mpath != NULL && strlen(mpath) != 0) {
250 crudpath.append(mpath);
251 crudpath.append(":");
252 }
253 crudpath.append(PACKAGE_PLUGIN_DIR);
254
255 AddLibrariesPath (crudpath);
256 }
257
258 CSAPI_TIER2 void
AddModule(Module * module)259 Plugins::AddModule (Module * module) {
260 list<Module>::iterator iter;
261
262 for (iter = removedList.begin(); iter != removedList.end(); ++iter) {
263 if (&(*iter) == module) {
264 modList.splice(modList.begin(), removedList, iter);
265 return;
266 }
267 }
268
269 modList.push_back (*module);
270 }
271
272 CSAPI_TIER2 void
RemoveLibrary(string name)273 Plugins::RemoveLibrary (string name) {
274 list<Module> * lM;
275
276 lM = LibraryModules (name);
277
278 list<Module>::iterator iter;
279
280 for (iter = lM->begin(); iter != lM->end(); ++iter) {
281 RemoveModule (&(*iter));
282 }
283 }
284
285 CSAPI_TIER2 void
RemoveModule(Module * module)286 Plugins::RemoveModule (Module * module) {
287 list<Module>::iterator iter;
288
289 for (iter = modList.begin(); iter != modList.end(); ++iter) {
290 if (&(*iter) == module) {
291 removedList.splice(removedList.begin(), modList, iter);
292 return;
293 }
294 }
295 }
296
297 // get a specific module of a given name
298 CSAPI_TIER2 Module *
GetModule(string name)299 Plugins::GetModule (string name) {
300 list<Module>::iterator iter;
301
302 for (iter = modList.begin(); iter != modList.end(); ++iter) {
303 if ((*iter).name() == name) {
304 return &(*iter);
305 }
306 }
307
308 return NULL;
309 }
310
311 CSAPI_TIER2 list<Module> *
LibraryModules(string name)312 Plugins::LibraryModules (string name) {
313 list<Module>::const_iterator iter;
314
315 for (iter = modList.begin(); iter != modList.end(); ++iter) {
316 if ((*iter).plib->filename() == name) {
317 return (*iter).plib->Modules();
318 }
319 }
320 return NULL;
321 }
322
323
324
325
326