Mercurial > hg > svcore
diff 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 |
line wrap: on
line diff
--- a/plugin/FeatureExtractionPluginFactory.cpp Thu Mar 30 15:00:22 2006 +0000 +++ b/plugin/FeatureExtractionPluginFactory.cpp Fri Mar 31 15:56:35 2006 +0000 @@ -22,6 +22,15 @@ #include "plugins/SpectralCentroid.h" //!!! #include "plugins/TonalChangeDetect.h" //!!! +#include "vamp/vamp.h" +#include "vamp-sdk/PluginHostAdapter.h" + +#include "base/System.h" + +#include <QDir> +#include <QFile> +#include <QFileInfo> + #include <iostream> static FeatureExtractionPluginFactory *_nativeInstance = 0; @@ -29,7 +38,7 @@ FeatureExtractionPluginFactory * FeatureExtractionPluginFactory::instance(QString pluginType) { - if (pluginType == "sv") { + if (pluginType == "vamp" || pluginType == "sv") { //!!! if (!_nativeInstance) { std::cerr << "FeatureExtractionPluginFactory::instance(" << pluginType.toStdString() << "): creating new FeatureExtractionPluginFactory" << std::endl; @@ -50,12 +59,43 @@ } std::vector<QString> +FeatureExtractionPluginFactory::getPluginPath() +{ + std::vector<QString> path; + std::string envPath; + + char *cpath = getenv("Vamp_PATH"); + if (cpath) envPath = cpath; + + if (envPath == "") { + //!!! system dependent + envPath = "/usr/local/lib/vamp:/usr/lib/vamp"; + char *chome = getenv("HOME"); + if (chome) { + envPath = std::string(chome) + "/vamp:" + + std::string(chome) + "/.vamp:" + envPath; + } + } + + std::string::size_type index = 0, newindex = 0; + + while ((newindex = envPath.find(':', index)) < envPath.size()) { + path.push_back(envPath.substr(index, newindex - index).c_str()); + index = newindex + 1; + } + + path.push_back(envPath.substr(index).c_str()); + + return path; +} + +std::vector<QString> FeatureExtractionPluginFactory::getAllPluginIdentifiers() { FeatureExtractionPluginFactory *factory; std::vector<QString> rv; - factory = instance("sv"); + factory = instance("vamp"); if (factory) { std::vector<QString> tmp = factory->getPluginIdentifiers(); for (size_t i = 0; i < tmp.size(); ++i) { @@ -77,48 +117,196 @@ rv.push_back("sv:_builtin:zerocrossing"); //!!! rv.push_back("sv:_builtin:spectralcentroid"); //!!! rv.push_back("sv:_builtin:tonalchange"); //!!! + + std::vector<QString> path = getPluginPath(); + + for (std::vector<QString>::iterator i = path.begin(); i != path.end(); ++i) { + + std::cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: scanning directory " << i->toStdString() << std::endl; + + QDir pluginDir(*i, PLUGIN_GLOB, + QDir::Name | QDir::IgnoreCase, + QDir::Files | QDir::Readable); + + for (unsigned int j = 0; j < pluginDir.count(); ++j) { + + QString soname = pluginDir.filePath(pluginDir[j]); + + void *libraryHandle = DLOPEN(soname, RTLD_LAZY); + + if (!libraryHandle) { + std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname.toStdString() << std::endl; + continue; + } + + VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) + DLSYM(libraryHandle, "vampGetPluginDescriptor"); + + if (!fn) { + std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname.toStdString() << std::endl; + if (DLCLOSE(libraryHandle) != 0) { + std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl; + } + continue; + } + + const VampPluginDescriptor *descriptor = 0; + int index = 0; + + while ((descriptor = fn(index))) { + QString id = QString("vamp:%1:%2").arg(soname).arg(descriptor->name); + rv.push_back(id); + std::cerr << "Found id " << id.toStdString() << std::endl; + ++index; + } + + if (DLCLOSE(libraryHandle) != 0) { + std::cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname.toStdString() << std::endl; + } + } + } + return rv; } -FeatureExtractionPlugin * +QString +FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir) +{ + QString file = ""; + + if (inDir != "") { + + QDir dir(inDir, PLUGIN_GLOB, + QDir::Name | QDir::IgnoreCase, + QDir::Files | QDir::Readable); + if (!dir.exists()) return ""; + + file = dir.filePath(QFileInfo(soname).fileName()); + if (QFileInfo(file).exists()) { + return file; + } + + for (unsigned int j = 0; j < dir.count(); ++j) { + file = dir.filePath(dir[j]); + if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) { + return file; + } + } + + return ""; + + } else { + + QFileInfo fi(soname); + if (fi.exists()) return soname; + + if (fi.isAbsolute() && fi.absolutePath() != "") { + file = findPluginFile(soname, fi.absolutePath()); + if (file != "") return file; + } + + std::vector<QString> path = getPluginPath(); + for (std::vector<QString>::iterator i = path.begin(); + i != path.end(); ++i) { + if (*i != "") { + file = findPluginFile(soname, *i); + if (file != "") return file; + } + } + + return ""; + } +} + +Vamp::Plugin * FeatureExtractionPluginFactory::instantiatePlugin(QString identifier, float inputSampleRate) { - QString type, soName, label; - PluginIdentifier::parseIdentifier(identifier, type, soName, label); - if (type != "sv") { + Vamp::Plugin *rv = 0; + + const VampPluginDescriptor *descriptor = 0; + int index = 0; + + QString type, soname, label; + PluginIdentifier::parseIdentifier(identifier, type, soname, label); + if (type != "vamp" && type != "sv") { //!!! std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type.toStdString() << std::endl; return 0; } //!!! - if (soName != PluginIdentifier::BUILTIN_PLUGIN_SONAME) { - std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Non-built-in plugins not yet supported (paradoxically enough)" << std::endl; - return 0; + if (type == "sv" && soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) { + + if (label == "beats") { + return new BeatDetector(inputSampleRate); //!!! + } + + if (label == "chromagram") { + return new ChromagramPlugin(inputSampleRate); //!!! + } + + if (label == "zerocrossing") { + return new ZeroCrossing(inputSampleRate); //!!! + } + + if (label == "spectralcentroid") { + return new SpectralCentroid(inputSampleRate); //!!! + } + + if (label == "tonalchange") { + return new TonalChangeDetect(inputSampleRate); //!!! + } + + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl; + + return 0; } - if (label == "beats") { - return new BeatDetector(inputSampleRate); //!!! + QString found = findPluginFile(soname); + + if (found == "") { + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname.toStdString() << std::endl; + } else if (found != soname) { + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: WARNING: Given library name was " << soname.toStdString() << ", found at " << found.toStdString() << std::endl; } - if (label == "chromagram") { - return new ChromagramPlugin(inputSampleRate); //!!! + soname = found; + + void *libraryHandle = DLOPEN(soname, RTLD_LAZY); + + if (!libraryHandle) { + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname.toStdString() << std::endl; + return 0; } - if (label == "zerocrossing") { - return new ZeroCrossing(inputSampleRate); //!!! + VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) + DLSYM(libraryHandle, "vampGetPluginDescriptor"); + + if (!fn) { + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname.toStdString() << std::endl; + goto done; } - if (label == "spectralcentroid") { - return new SpectralCentroid(inputSampleRate); //!!! + while ((descriptor = fn(index))) { + if (label == descriptor->name) break; + ++index; } - if (label == "tonalchange") { - return new TonalChangeDetect(inputSampleRate); //!!! + if (!descriptor) { + std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label.toStdString() << "\" in library " << soname.toStdString() << std::endl; + goto done; } - std::cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Unknown plugin \"" << identifier.toStdString() << "\"" << std::endl; - - return 0; + rv = new Vamp::PluginHostAdapter(descriptor, inputSampleRate); + + //!!! need to dlclose() when plugins from a given library are unloaded + +done: + if (!rv) { + if (DLCLOSE(libraryHandle) != 0) { + std::cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname.toStdString() << std::endl; + } + } + return rv; }