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