19 #include <vamp-hostsdk/PluginHostAdapter.h> 20 #include <vamp-hostsdk/PluginWrapper.h> 29 #include <QTextStream> 36 #include <QMutexLocker> 46 PluginWrapper(plugin), m_factory(factory) { }
55 Vamp::Plugin *p = m_plugin;
57 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 58 SVCERR <<
"PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter(" 59 <<
this <<
" for plugin " << p <<
")" << endl;
66 if (m_factory) m_factory->pluginDeleted(p);
72 if (!m_pluginPath.empty())
return m_pluginPath;
74 vector<string> p = Vamp::PluginHostAdapter::getPluginPath();
75 for (
size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str());
80 QList<PluginScan::Candidate>
83 #ifdef HAVE_PLUGIN_CHECKER_HELPER 87 auto path = Vamp::PluginHostAdapter::getPluginPath();
88 QList<PluginScan::Candidate> candidates;
89 for (
string dirname: path) {
90 SVDEBUG <<
"NativeVampPluginFactory: scanning directory myself: " 93 #define PLUGIN_GLOB "*.dll" 94 #elif defined(__APPLE__) 95 #define PLUGIN_GLOB "*.dylib *.so" 97 #define PLUGIN_GLOB "*.so" 100 QDir::Name | QDir::IgnoreCase,
101 QDir::Files | QDir::Readable);
103 for (
unsigned int i = 0; i < dir.count(); ++i) {
104 QString libpath = dir.filePath(dir[i]);
105 candidates.push_back({ libpath,
"" });
116 Profiler profiler(
"NativeVampPluginFactory::getPluginIdentifiers");
118 QMutexLocker locker(&m_mutex);
120 if (!m_identifiers.empty()) {
121 return m_identifiers;
126 SVDEBUG <<
"INFO: Have " << candidates.size() <<
" candidate Vamp plugin libraries" << endl;
128 for (
auto candidate : candidates) {
130 QString libpath = candidate.libraryPath;
132 SVDEBUG <<
"INFO: Considering candidate Vamp plugin library " << libpath << endl;
134 void *libraryHandle =
DLOPEN(libpath, RTLD_LAZY | RTLD_LOCAL);
136 if (!libraryHandle) {
137 SVDEBUG <<
"WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to load library " << libpath <<
": " <<
DLERROR() << endl;
141 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
142 DLSYM(libraryHandle,
"vampGetPluginDescriptor");
145 SVDEBUG <<
"WARNING: NativeVampPluginFactory::getPluginIdentifiers: No descriptor function in " << libpath << endl;
146 if (
DLCLOSE(libraryHandle) != 0) {
147 SVDEBUG <<
"WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl;
152 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 153 SVCERR <<
"NativeVampPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
156 const VampPluginDescriptor *descriptor =
nullptr;
159 map<string, int> known;
162 while ((descriptor = fn(VAMP_API_VERSION, index))) {
164 if (known.find(descriptor->identifier) != known.end()) {
165 SVDEBUG <<
"WARNING: NativeVampPluginFactory::getPluginIdentifiers: Plugin library " 167 <<
" returns the same plugin identifier \"" 168 << descriptor->identifier <<
"\" at indices " 169 << known[descriptor->identifier] <<
" and " 171 SVDEBUG <<
"NativeVampPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl;
175 known[descriptor->identifier] = index;
185 while ((descriptor = fn(VAMP_API_VERSION, index))) {
188 (
"vamp", libpath, descriptor->identifier);
189 m_identifiers.push_back(
id);
190 m_libraries[id] = libpath;
191 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 192 SVCERR <<
"NativeVampPluginFactory::getPluginIdentifiers: Found plugin id " <<
id <<
" at index " << index << endl;
198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 199 SVCERR <<
"NativeVampPluginFactory::getPluginIdentifiers: unloading library " << libraryHandle << endl;
202 if (
DLCLOSE(libraryHandle) != 0) {
203 SVDEBUG <<
"WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl;
212 return m_identifiers;
220 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 221 SVCERR <<
"NativeVampPluginFactory::findPluginFile(\"" 222 << soname <<
"\", \"" << inDir <<
"\")" 229 QDir::Name | QDir::IgnoreCase,
230 QDir::Files | QDir::Readable);
231 if (!dir.exists())
return "";
233 file = dir.filePath(QFileInfo(soname).fileName());
235 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) {
237 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 238 SVCERR <<
"NativeVampPluginFactory::findPluginFile: " 239 <<
"found trivially at " << file << endl;
245 for (
unsigned int j = 0; j < dir.count(); ++j) {
246 file = dir.filePath(dir[j]);
247 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
249 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 250 SVCERR <<
"NativeVampPluginFactory::findPluginFile: " 251 <<
"found \"" << soname <<
"\" at " << file << endl;
258 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 259 SVCERR <<
"NativeVampPluginFactory::findPluginFile (with dir): " 260 <<
"not found" << endl;
267 QFileInfo fi(soname);
269 if (fi.isAbsolute() && fi.exists() && fi.isFile()) {
270 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 271 SVCERR <<
"NativeVampPluginFactory::findPluginFile: " 272 <<
"found trivially at " << soname << endl;
277 if (fi.isAbsolute() && fi.absolutePath() !=
"") {
278 file = findPluginFile(soname, fi.absolutePath());
279 if (file !=
"")
return file;
282 vector<QString> path = getPluginPath();
283 for (vector<QString>::iterator i = path.begin();
284 i != path.end(); ++i) {
286 file = findPluginFile(soname, *i);
287 if (file !=
"")
return file;
291 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 292 SVCERR <<
"NativeVampPluginFactory::findPluginFile: " 293 <<
"not found" << endl;
300 std::shared_ptr<Vamp::Plugin>
304 Profiler profiler(
"NativeVampPluginFactory::instantiatePlugin");
306 std::shared_ptr<Vamp::Plugin> rv =
nullptr;
307 Vamp::PluginHostAdapter *plugin =
nullptr;
309 const VampPluginDescriptor *descriptor =
nullptr;
312 QString type, soname, label;
314 if (type !=
"vamp") {
315 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 316 SVCERR <<
"NativeVampPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
321 QString found = findPluginFile(soname);
324 SVDEBUG <<
"NativeVampPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
326 }
else if (found != soname) {
328 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 329 SVCERR <<
"NativeVampPluginFactory::instantiatePlugin: Given library name was " << soname <<
", found at " << found << endl;
330 SVCERR << soname <<
" -> " << found << endl;
337 void *libraryHandle =
DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
339 if (!libraryHandle) {
340 SVDEBUG <<
"NativeVampPluginFactory::instantiatePlugin: Failed to load library " << soname <<
": " <<
DLERROR() << endl;
344 VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
345 DLSYM(libraryHandle,
"vampGetPluginDescriptor");
348 SVDEBUG <<
"NativeVampPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl;
352 while ((descriptor = fn(VAMP_API_VERSION, index))) {
353 if (label == descriptor->identifier)
break;
358 SVDEBUG <<
"NativeVampPluginFactory::instantiatePlugin: Failed to find plugin \"" << label <<
"\" in library " << soname << endl;
362 plugin =
new Vamp::PluginHostAdapter(descriptor,
float(inputSampleRate));
365 m_handleMap[plugin] = libraryHandle;
366 rv = std::shared_ptr<Vamp::Plugin>
370 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 372 SVCERR <<
"NativeVampPluginFactory::instantiatePlugin: Instantiated plugin " << label <<
" from library " << soname <<
": descriptor " << descriptor <<
", rv "<< rv <<
", label " << rv->getName() <<
", outputs " << rv->getOutputDescriptors().size() << endl;
378 SVCERR <<
"NativeVampPluginFactory::instantiatePlugin: Failed to construct plugin" << endl;
379 if (
DLCLOSE(libraryHandle) != 0) {
380 SVDEBUG <<
"WARNING: NativeVampPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
390 void *handle = m_handleMap[plugin];
393 m_handleMap.erase(plugin);
395 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 396 SVCERR <<
"NativeVampPluginFactory::pluginDeleted: Removed from handle map, which now has " << m_handleMap.size() <<
" entries" << endl;
399 for (
auto h: m_handleMap) {
400 if (h.second == handle) {
402 SVDEBUG <<
"NativeVampPluginFactory::pluginDeleted: Not unloading library " << handle <<
" as other plugins are still loaded from it" << endl;
407 SVDEBUG <<
"NativeVampPluginFactory::pluginDeleted: Unloading library " << handle <<
" after last plugin from this library " << plugin <<
" was deleted" << endl;
414 return m_taxonomy[identifier];
420 return m_libraries[identifier];
426 vector<QString> pluginPath = getPluginPath();
427 vector<QString> path;
429 for (
size_t i = 0; i < pluginPath.size(); ++i) {
430 if (pluginPath[i].contains(
"/lib/")) {
431 QString p(pluginPath[i]);
433 p.replace(
"/lib/",
"/share/");
436 path.push_back(pluginPath[i]);
439 for (
size_t i = 0; i < path.size(); ++i) {
441 QDir dir(path[i],
"*.cat");
444 for (
unsigned int j = 0; j < dir.count(); ++j) {
446 QFile file(path[i] +
"/" + dir[j]);
450 if (file.open(QIODevice::ReadOnly)) {
451 QTextStream stream(&file);
454 while (!stream.atEnd()) {
455 line = stream.readLine();
457 (line.section(
"::", 0, 0));
458 QString cat = line.section(
"::", 1, 1);
459 m_taxonomy[id] = cat;
466 piper_vamp::PluginStaticData
469 QMutexLocker locker(&m_mutex);
471 if (m_pluginData.find(identifier) != m_pluginData.end()) {
472 return m_pluginData[identifier];
475 QString type, soname, label;
477 std::string pluginKey = (soname +
":" + label).toStdString();
479 std::vector<std::string> catlist;
480 for (
auto s: getPluginCategory(identifier).split(
" > ")) {
481 catlist.push_back(s.toStdString());
484 std::shared_ptr<Vamp::Plugin> p = instantiatePlugin(identifier, 44100);
487 auto psd = piper_vamp::PluginStaticData::fromPlugin(pluginKey,
491 m_pluginData[identifier] = psd;
PluginDeletionNotifyAdapter(Vamp::Plugin *plugin, NativeVampPluginFactory *factory)
double sv_samplerate_t
Sample rate.
static QList< PluginScan::Candidate > getCandidateLibraries()
~PluginDeletionNotifyAdapter() override
static QString canonicalise(QString identifier)
QList< Candidate > getCandidateLibrariesFor(PluginType) const
Return the candidate plugin libraries of the given type that were found by helpers during the startup...
virtual std::shared_ptr< Vamp::Plugin > instantiatePlugin(QString identifier, sv_samplerate_t inputSampleRate) override
Instantiate (load) and return pointer to the plugin with the given identifier, at the given sample ra...
QString findPluginFile(QString soname, QString inDir="")
static void parseIdentifier(QString identifier, QString &type, QString &soName, QString &label)
FeatureExtractionPluginFactory type for Vamp plugins hosted in-process.
static QString createIdentifier(QString type, QString soName, QString label)
virtual piper_vamp::PluginStaticData getPluginStaticData(QString identifier) override
Return static data for the given plugin.
virtual QString getPluginLibraryPath(QString identifier) override
Get the full file path (including both directory and filename) of the library file that provides a gi...
static PluginScan * getInstance()
virtual std::vector< QString > getPluginIdentifiers(QString &errorMessage) override
Return all installed plugin identifiers.
std::vector< QString > getPluginPath()
void pluginDeleted(Vamp::Plugin *)
void RestoreStartupLocale()
NativeVampPluginFactory * m_factory
virtual QString getPluginCategory(QString identifier) override
Get category metadata about a plugin (without instantiating it).
Profile point instance class.