comparison vamp-sdk/hostext/PluginLoader.cpp @ 58:0284955e31e5 host-factory-stuff

* reshuffle
author cannam
date Thu, 24 May 2007 10:05:00 +0000
parents vamp-hostsdk/PluginLoader.cpp@09a1aac6c362
children fa79c4ec847d
comparison
equal deleted inserted replaced
57:09a1aac6c362 58:0284955e31e5
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Vamp
5
6 An API for audio analysis and feature extraction plugins.
7
8 Centre for Digital Music, Queen Mary, University of London.
9 Copyright 2006 Chris Cannam.
10
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 Except as contained in this notice, the names of the Centre for
31 Digital Music; Queen Mary, University of London; and Chris Cannam
32 shall not be used in advertising or otherwise to promote the sale,
33 use or other dealings in this Software without prior written
34 authorization.
35 */
36
37 #include "PluginLoader.h"
38 #include "PluginHostAdapter.h"
39
40 #include "system.h"
41
42 #include <fstream>
43
44 #include <dirent.h> // POSIX directory open and read
45
46 using namespace std;
47
48 namespace Vamp {
49
50 PluginLoader::PluginLoader()
51 {
52 }
53
54 PluginLoader::~PluginLoader()
55 {
56 }
57
58 vector<PluginLoader::PluginKey>
59 PluginLoader::listPlugins()
60 {
61 if (m_pluginLibraryMap.empty()) {
62
63 vector<string> path = PluginHostAdapter::getPluginPath();
64
65 size_t suffixLen = strlen(PLUGIN_SUFFIX);
66
67 for (size_t i = 0; i < path.size(); ++i) {
68
69 vector<string> files = getFilesInDir(path[i], PLUGIN_SUFFIX);
70
71
72 for (vector<string>::iterator fi = files.begin();
73 fi != files.end(); ++fi) {
74
75 string basename = *fi;
76 basename = basename.substr(0, basename.length() - suffixLen - 1);
77
78 string fullPath = path[i];
79 fullPath = fullPath + "/" + *fi; //!!! systemize
80 void *handle = DLOPEN(fullPath, RTLD_LAZY);
81
82 if (!handle) {
83 cerr << "Vamp::PluginLoader: " << *fi
84 << ": unable to load library (" << DLERROR()
85 << ")" << endl;
86 continue;
87 }
88
89 VampGetPluginDescriptorFunction fn =
90 (VampGetPluginDescriptorFunction)DLSYM
91 (handle, "vampGetPluginDescriptor");
92
93 if (!fn) {
94 DLCLOSE(handle);
95 continue;
96 }
97
98 int index = 0;
99 const VampPluginDescriptor *descriptor = 0;
100
101 while ((descriptor = fn(VAMP_API_VERSION, index))) {
102 PluginKey key = basename + ":" + descriptor->identifier;
103 if (m_pluginLibraryMap.find(key) ==
104 m_pluginLibraryMap.end()) {
105 m_pluginLibraryMap[key] = fullPath;
106 }
107 ++index;
108 }
109
110 DLCLOSE(handle);
111 }
112 }
113 }
114
115 vector<PluginKey> plugins;
116 for (map<PluginKey, string>::iterator mi =
117 m_pluginLibraryMap.begin();
118 mi != m_pluginLibraryMap.end(); ++mi) {
119 plugins.push_back(mi->first);
120 }
121
122 return plugins;
123 }
124
125 PluginLoader::PluginCategoryHierarchy
126 PluginLoader::getPluginCategory(PluginKey plugin)
127 {
128 if (m_taxonomy.empty()) generateTaxonomy();
129 if (m_taxonomy.find(plugin) == m_taxonomy.end()) return PluginCategoryHierarchy();
130 return m_taxonomy[plugin];
131 }
132
133 string
134 PluginLoader::getLibraryPathForPlugin(PluginKey plugin)
135 {
136 if (m_pluginLibraryMap.empty()) (void)listPlugins();
137 if (m_pluginLibraryMap.find(plugin) == m_pluginLibraryMap.end()) return "";
138 return m_pluginLibraryMap[plugin];
139 }
140
141 Plugin *
142 PluginLoader::load(PluginKey key, float inputSampleRate)
143 {
144 string fullPath = getLibraryPathForPlugin(key);
145 if (fullPath == "") return 0;
146
147 string::size_type ki = key.find(':');
148 if (ki == string::npos) {
149 //!!! flag error
150 return 0;
151 }
152
153 string identifier = key.substr(ki + 1);
154
155 void *handle = DLOPEN(fullPath, RTLD_LAZY);
156
157 if (!handle) {
158 cerr << "Vamp::PluginLoader: " << fullPath
159 << ": unable to load library (" << DLERROR()
160 << ")" << endl;
161 return 0;
162 }
163
164 VampGetPluginDescriptorFunction fn =
165 (VampGetPluginDescriptorFunction)DLSYM
166 (handle, "vampGetPluginDescriptor");
167
168 if (!fn) {
169 //!!! refcount this! --!!! no, POSIX says dlopen/dlclose will
170 // reference count. check on win32
171 DLCLOSE(handle);
172 return 0;
173 }
174
175 int index = 0;
176 const VampPluginDescriptor *descriptor = 0;
177
178 while ((descriptor = fn(VAMP_API_VERSION, index))) {
179 if (string(descriptor->identifier) == identifier) {
180 return new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
181 }
182 ++index;
183 }
184
185 //!!! flag error
186 return 0;
187 }
188
189 vector<string>
190 PluginLoader::getFilesInDir(string dir, string extension)
191 {
192 vector<string> files;
193
194 DIR *d = opendir(dir.c_str());
195 if (!d) return files;
196
197 struct dirent *e = 0;
198 while ((e = readdir(d))) {
199
200 if (!(e->d_type & DT_REG) || !e->d_name) {
201 continue;
202 }
203
204 int len = strlen(e->d_name);
205 if (len < int(extension.length() + 2) ||
206 e->d_name[len - extension.length() - 1] != '.' ||
207 strcmp(e->d_name + len - extension.length(), extension.c_str())) {
208 continue;
209 }
210
211 files.push_back(e->d_name);
212 }
213
214 closedir(d);
215
216 return files;
217 }
218
219 void
220 PluginLoader::generateTaxonomy()
221 {
222 // cerr << "PluginLoader::generateTaxonomy" << endl;
223
224 vector<string> path = PluginHostAdapter::getPluginPath();
225 string libfragment = "/lib/";
226 vector<string> catpath;
227
228 string suffix = "cat";
229
230 for (vector<string>::iterator i = path.begin();
231 i != path.end(); ++i) {
232
233 string dir = *i;
234 string::size_type li = dir.find(libfragment);
235
236 if (li != string::npos) {
237 catpath.push_back
238 (dir.substr(0, li)
239 + "/share/"
240 + dir.substr(li + libfragment.length()));
241 }
242
243 catpath.push_back(dir);
244 }
245
246 char buffer[1024];
247
248 for (vector<string>::iterator i = catpath.begin();
249 i != catpath.end(); ++i) {
250
251 vector<string> files = getFilesInDir(*i, suffix);
252
253 for (vector<string>::iterator fi = files.begin();
254 fi != files.end(); ++fi) {
255
256 string filepath = *i + "/" + *fi; //!!! systemize
257 ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
258
259 if (is.fail()) {
260 // cerr << "failed to open: " << filepath << endl;
261 continue;
262 }
263
264 // cerr << "opened: " << filepath << endl;
265
266 while (!!is.getline(buffer, 1024)) {
267
268 string line(buffer);
269
270 // cerr << "line = " << line << endl;
271
272 string::size_type di = line.find("::");
273 if (di == string::npos) continue;
274
275 string id = line.substr(0, di);
276 string encodedCat = line.substr(di + 2);
277
278 if (id.substr(0, 5) != "vamp:") continue;
279 id = id.substr(5);
280
281 while (encodedCat.length() >= 1 &&
282 encodedCat[encodedCat.length()-1] == '\r') {
283 encodedCat = encodedCat.substr(0, encodedCat.length()-1);
284 }
285
286 // cerr << "id = " << id << ", cat = " << encodedCat << endl;
287
288 PluginCategoryHierarchy category;
289 string::size_type ai;
290 while ((ai = encodedCat.find(" > ")) != string::npos) {
291 category.push_back(encodedCat.substr(0, ai));
292 encodedCat = encodedCat.substr(ai + 3);
293 }
294 if (encodedCat != "") category.push_back(encodedCat);
295
296 m_taxonomy[id] = category;
297 }
298 }
299 }
300 }
301
302
303 }