Mercurial > hg > svcore
comparison plugin/FeatureExtractionPluginFactory.cpp @ 66:7afcfe666910
* Modify to use Vamp SDK for proper feature extraction plugins.
Requires that the vamp-plugin-sdk directory tree be present below
plugin/ (it's separate in Subversion).
author | Chris Cannam |
---|---|
date | Fri, 31 Mar 2006 15:56:35 +0000 |
parents | d397ea0a79f5 |
children | e32c6a6cb40f |
comparison
equal
deleted
inserted
replaced
65:e1aad27029e3 | 66:7afcfe666910 |
---|---|
20 #include "plugins/ChromagramPlugin.h" //!!! | 20 #include "plugins/ChromagramPlugin.h" //!!! |
21 #include "plugins/ZeroCrossing.h" //!!! | 21 #include "plugins/ZeroCrossing.h" //!!! |
22 #include "plugins/SpectralCentroid.h" //!!! | 22 #include "plugins/SpectralCentroid.h" //!!! |
23 #include "plugins/TonalChangeDetect.h" //!!! | 23 #include "plugins/TonalChangeDetect.h" //!!! |
24 | 24 |
25 #include "vamp/vamp.h" | |
26 #include "vamp-sdk/PluginHostAdapter.h" | |
27 | |
28 #include "base/System.h" | |
29 | |
30 #include <QDir> | |
31 #include <QFile> | |
32 #include <QFileInfo> | |
33 | |
25 #include <iostream> | 34 #include <iostream> |
26 | 35 |
27 static FeatureExtractionPluginFactory *_nativeInstance = 0; | 36 static FeatureExtractionPluginFactory *_nativeInstance = 0; |
28 | 37 |
29 FeatureExtractionPluginFactory * | 38 FeatureExtractionPluginFactory * |
30 FeatureExtractionPluginFactory::instance(QString pluginType) | 39 FeatureExtractionPluginFactory::instance(QString pluginType) |
31 { | 40 { |
32 if (pluginType == "sv") { | 41 if (pluginType == "vamp" || pluginType == "sv") { //!!! |
33 if (!_nativeInstance) { | 42 if (!_nativeInstance) { |
34 std::cerr << "FeatureExtractionPluginFactory::instance(" << pluginType.toStdString() | 43 std::cerr << "FeatureExtractionPluginFactory::instance(" << pluginType.toStdString() |
35 << "): creating new FeatureExtractionPluginFactory" << std::endl; | 44 << "): creating new FeatureExtractionPluginFactory" << std::endl; |
36 _nativeInstance = new FeatureExtractionPluginFactory(); | 45 _nativeInstance = new FeatureExtractionPluginFactory(); |
37 } | 46 } |
48 PluginIdentifier::parseIdentifier(identifier, type, soName, label); | 57 PluginIdentifier::parseIdentifier(identifier, type, soName, label); |
49 return instance(type); | 58 return instance(type); |
50 } | 59 } |
51 | 60 |
52 std::vector<QString> | 61 std::vector<QString> |
62 FeatureExtractionPluginFactory::getPluginPath() | |
63 { | |
64 std::vector<QString> path; | |
65 std::string envPath; | |
66 | |
67 char *cpath = getenv("Vamp_PATH"); | |
68 if (cpath) envPath = cpath; | |
69 | |
70 if (envPath == "") { | |
71 //!!! system dependent | |
72 envPath = "/usr/local/lib/vamp:/usr/lib/vamp"; | |
73 char *chome = getenv("HOME"); | |
74 if (chome) { | |
75 envPath = std::string(chome) + "/vamp:" + | |
76 std::string(chome) + "/.vamp:" + envPath; | |
77 } | |
78 } | |
79 | |
80 std::string::size_type index = 0, newindex = 0; | |
81 | |
82 while ((newindex = envPath.find(':', index)) < envPath.size()) { | |
83 path.push_back(envPath.substr(index, newindex - index).c_str()); | |
84 index = newindex + 1; | |
85 } | |
86 | |
87 path.push_back(envPath.substr(index).c_str()); | |
88 | |
89 return path; | |
90 } | |
91 | |
92 std::vector<QString> | |
53 FeatureExtractionPluginFactory::getAllPluginIdentifiers() | 93 FeatureExtractionPluginFactory::getAllPluginIdentifiers() |
54 { | 94 { |
55 FeatureExtractionPluginFactory *factory; | 95 FeatureExtractionPluginFactory *factory; |
56 std::vector<QString> rv; | 96 std::vector<QString> rv; |
57 | 97 |
58 factory = instance("sv"); | 98 factory = instance("vamp"); |
59 if (factory) { | 99 if (factory) { |
60 std::vector<QString> tmp = factory->getPluginIdentifiers(); | 100 std::vector<QString> tmp = factory->getPluginIdentifiers(); |
61 for (size_t i = 0; i < tmp.size(); ++i) { | 101 for (size_t i = 0; i < tmp.size(); ++i) { |
62 rv.push_back(tmp[i]); | 102 rv.push_back(tmp[i]); |
63 } | 103 } |
75 rv.push_back("sv:_builtin:beats"); //!!! | 115 rv.push_back("sv:_builtin:beats"); //!!! |
76 rv.push_back("sv:_builtin:chromagram"); //!!! | 116 rv.push_back("sv:_builtin:chromagram"); //!!! |
77 rv.push_back("sv:_builtin:zerocrossing"); //!!! | 117 rv.push_back("sv:_builtin:zerocrossing"); //!!! |
78 rv.push_back("sv:_builtin:spectralcentroid"); //!!! | 118 rv.push_back("sv:_builtin:spectralcentroid"); //!!! |
79 rv.push_back("sv:_builtin:tonalchange"); //!!! | 119 rv.push_back("sv:_builtin:tonalchange"); //!!! |
120 | |
121 std::vector<QString> path = getPluginPath(); | |
122 | |
123 for (std::vector<QString>::iterator i = path.begin(); i != path.end(); ++i) { | |
124 | |
125 std::cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << i->toStdString() << std::endl; | |
126 | |
127 QDir pluginDir(*i, PLUGIN_GLOB, | |
128 QDir::Name | QDir::IgnoreCase, | |
129 QDir::Files | QDir::Readable); | |
130 | |
131 for (unsigned int j = 0; j < pluginDir.count(); ++j) { | |
132 | |
133 QString soname = pluginDir.filePath(pluginDir[j]); | |
134 | |
135 void *libraryHandle = DLOPEN(soname, RTLD_LAZY); | |
136 | |
137 if (!libraryHandle) { | |
138 std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname.toStdString() << std::endl; | |
139 continue; | |
140 } | |
141 | |
142 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) | |
143 DLSYM(libraryHandle, "vampGetPluginDescriptor"); | |
144 | |
145 if (!fn) { | |
146 std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname.toStdString() << std::endl; | |
147 if (DLCLOSE(libraryHandle) != 0) { | |
148 std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl; | |
149 } | |
150 continue; | |
151 } | |
152 | |
153 const VampPluginDescriptor *descriptor = 0; | |
154 int index = 0; | |
155 | |
156 while ((descriptor = fn(index))) { | |
157 QString id = QString("vamp:%1:%2").arg(soname).arg(descriptor->name); | |
158 rv.push_back(id); | |
159 std::cerr << "Found id " << id.toStdString() << std::endl; | |
160 ++index; | |
161 } | |
162 | |
163 if (DLCLOSE(libraryHandle) != 0) { | |
164 std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl; | |
165 } | |
166 } | |
167 } | |
168 | |
80 return rv; | 169 return rv; |
81 } | 170 } |
82 | 171 |
83 FeatureExtractionPlugin * | 172 QString |
173 FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir) | |
174 { | |
175 QString file = ""; | |
176 | |
177 if (inDir != "") { | |
178 | |
179 QDir dir(inDir, PLUGIN_GLOB, | |
180 QDir::Name | QDir::IgnoreCase, | |
181 QDir::Files | QDir::Readable); | |
182 if (!dir.exists()) return ""; | |
183 | |
184 file = dir.filePath(QFileInfo(soname).fileName()); | |
185 if (QFileInfo(file).exists()) { | |
186 return file; | |
187 } | |
188 | |
189 for (unsigned int j = 0; j < dir.count(); ++j) { | |
190 file = dir.filePath(dir[j]); | |
191 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) { | |
192 return file; | |
193 } | |
194 } | |
195 | |
196 return ""; | |
197 | |
198 } else { | |
199 | |
200 QFileInfo fi(soname); | |
201 if (fi.exists()) return soname; | |
202 | |
203 if (fi.isAbsolute() && fi.absolutePath() != "") { | |
204 file = findPluginFile(soname, fi.absolutePath()); | |
205 if (file != "") return file; | |
206 } | |
207 | |
208 std::vector<QString> path = getPluginPath(); | |
209 for (std::vector<QString>::iterator i = path.begin(); | |
210 i != path.end(); ++i) { | |
211 if (*i != "") { | |
212 file = findPluginFile(soname, *i); | |
213 if (file != "") return file; | |
214 } | |
215 } | |
216 | |
217 return ""; | |
218 } | |
219 } | |
220 | |
221 Vamp::Plugin * | |
84 FeatureExtractionPluginFactory::instantiatePlugin(QString identifier, | 222 FeatureExtractionPluginFactory::instantiatePlugin(QString identifier, |
85 float inputSampleRate) | 223 float inputSampleRate) |
86 { | 224 { |
87 QString type, soName, label; | 225 Vamp::Plugin *rv = 0; |
88 PluginIdentifier::parseIdentifier(identifier, type, soName, label); | 226 |
89 if (type != "sv") { | 227 const VampPluginDescriptor *descriptor = 0; |
228 int index = 0; | |
229 | |
230 QString type, soname, label; | |
231 PluginIdentifier::parseIdentifier(identifier, type, soname, label); | |
232 if (type != "vamp" && type != "sv") { //!!! | |
90 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type.toStdString() << std::endl; | 233 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type.toStdString() << std::endl; |
91 return 0; | 234 return 0; |
92 } | 235 } |
93 | 236 |
94 //!!! | 237 //!!! |
95 if (soName != PluginIdentifier::BUILTIN_PLUGIN_SONAME) { | 238 if (type == "sv" && soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) { |
96 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Non-built-in plugins not yet supported (paradoxically enough)" << std::endl; | 239 |
97 return 0; | 240 if (label == "beats") { |
98 } | 241 return new BeatDetector(inputSampleRate); //!!! |
99 | 242 } |
100 if (label == "beats") { | 243 |
101 return new BeatDetector(inputSampleRate); //!!! | 244 if (label == "chromagram") { |
102 } | 245 return new ChromagramPlugin(inputSampleRate); //!!! |
103 | 246 } |
104 if (label == "chromagram") { | 247 |
105 return new ChromagramPlugin(inputSampleRate); //!!! | 248 if (label == "zerocrossing") { |
106 } | 249 return new ZeroCrossing(inputSampleRate); //!!! |
107 | 250 } |
108 if (label == "zerocrossing") { | 251 |
109 return new ZeroCrossing(inputSampleRate); //!!! | 252 if (label == "spectralcentroid") { |
110 } | 253 return new SpectralCentroid(inputSampleRate); //!!! |
111 | 254 } |
112 if (label == "spectralcentroid") { | 255 |
113 return new SpectralCentroid(inputSampleRate); //!!! | 256 if (label == "tonalchange") { |
114 } | 257 return new TonalChangeDetect(inputSampleRate); //!!! |
115 | 258 } |
116 if (label == "tonalchange") { | 259 |
117 return new TonalChangeDetect(inputSampleRate); //!!! | 260 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl; |
118 } | 261 |
119 | 262 return 0; |
120 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl; | 263 } |
121 | 264 |
122 return 0; | 265 QString found = findPluginFile(soname); |
123 } | 266 |
124 | 267 if (found == "") { |
268 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname.toStdString() << std::endl; | |
269 } else if (found != soname) { | |
270 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: WARNING: Given library name was " << soname.toStdString() << ", found at " << found.toStdString() << std::endl; | |
271 } | |
272 | |
273 soname = found; | |
274 | |
275 void *libraryHandle = DLOPEN(soname, RTLD_LAZY); | |
276 | |
277 if (!libraryHandle) { | |
278 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname.toStdString() << std::endl; | |
279 return 0; | |
280 } | |
281 | |
282 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) | |
283 DLSYM(libraryHandle, "vampGetPluginDescriptor"); | |
284 | |
285 if (!fn) { | |
286 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname.toStdString() << std::endl; | |
287 goto done; | |
288 } | |
289 | |
290 while ((descriptor = fn(index))) { | |
291 if (label == descriptor->name) break; | |
292 ++index; | |
293 } | |
294 | |
295 if (!descriptor) { | |
296 std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label.toStdString() << "\" in library " << soname.toStdString() << std::endl; | |
297 goto done; | |
298 } | |
299 | |
300 rv = new Vamp::PluginHostAdapter(descriptor, inputSampleRate); | |
301 | |
302 //!!! need to dlclose() when plugins from a given library are unloaded | |
303 | |
304 done: | |
305 if (!rv) { | |
306 if (DLCLOSE(libraryHandle) != 0) { | |
307 std::cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname.toStdString() << std::endl; | |
308 } | |
309 } | |
310 return rv; | |
311 } | |
312 |