annotate src/vamp-hostsdk/PluginLoader.cpp @ 434:e979a9c4ffb6 vampipe

Switch from Cross FFT with option of FFTW build, to KissFFT only (code bundled). This is much faster than the default build and simpler than managing two options.
author Chris Cannam
date Tue, 16 Aug 2016 16:04:09 +0100
parents 2819b5c9a395
children c053e5e79b8f
rev   line source
cannam@233 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@233 2
cannam@233 3 /*
cannam@233 4 Vamp
cannam@233 5
cannam@233 6 An API for audio analysis and feature extraction plugins.
cannam@233 7
cannam@233 8 Centre for Digital Music, Queen Mary, University of London.
Chris@423 9 Copyright 2006-2016 Chris Cannam and QMUL.
cannam@233 10
cannam@233 11 Permission is hereby granted, free of charge, to any person
cannam@233 12 obtaining a copy of this software and associated documentation
cannam@233 13 files (the "Software"), to deal in the Software without
cannam@233 14 restriction, including without limitation the rights to use, copy,
cannam@233 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@233 16 of the Software, and to permit persons to whom the Software is
cannam@233 17 furnished to do so, subject to the following conditions:
cannam@233 18
cannam@233 19 The above copyright notice and this permission notice shall be
cannam@233 20 included in all copies or substantial portions of the Software.
cannam@233 21
cannam@233 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@233 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@233 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@233 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@233 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@233 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@233 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@233 29
cannam@233 30 Except as contained in this notice, the names of the Centre for
cannam@233 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@233 32 shall not be used in advertising or otherwise to promote the sale,
cannam@233 33 use or other dealings in this Software without prior written
cannam@233 34 authorization.
cannam@233 35 */
cannam@233 36
cannam@233 37 #include <vamp-hostsdk/PluginLoader.h>
cannam@233 38 #include <vamp-hostsdk/PluginInputDomainAdapter.h>
cannam@233 39 #include <vamp-hostsdk/PluginChannelAdapter.h>
cannam@233 40 #include <vamp-hostsdk/PluginBufferingAdapter.h>
Chris@390 41 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@390 42
Chris@390 43 #include <vamp/vamp.h>
Chris@390 44
Chris@390 45 #include "Files.h"
cannam@233 46
cannam@233 47 #include <fstream>
cannam@233 48
cannam@233 49 using namespace std;
cannam@233 50
cannam@263 51 _VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.cpp)
cannam@263 52
cannam@233 53 namespace Vamp {
cannam@233 54
cannam@233 55 namespace HostExt {
cannam@233 56
cannam@233 57 class PluginLoader::Impl
cannam@233 58 {
cannam@233 59 public:
cannam@233 60 Impl();
cannam@233 61 virtual ~Impl();
cannam@233 62
cannam@233 63 PluginKeyList listPlugins();
Chris@426 64 PluginStaticDataList listPluginData();
cannam@233 65
cannam@233 66 Plugin *loadPlugin(PluginKey key,
cannam@233 67 float inputSampleRate,
cannam@233 68 int adapterFlags);
cannam@233 69
Chris@423 70 LoadResponse loadPlugin(LoadRequest req);
Chris@423 71
Chris@431 72 ConfigurationResponse configurePlugin(ConfigurationRequest req);
Chris@423 73
cannam@233 74 PluginKey composePluginKey(string libraryName, string identifier);
cannam@233 75
cannam@233 76 PluginCategoryHierarchy getPluginCategory(PluginKey key);
cannam@233 77
cannam@233 78 string getLibraryPathForPlugin(PluginKey key);
cannam@233 79
cannam@233 80 static void setInstanceToClean(PluginLoader *instance);
cannam@233 81
cannam@233 82 protected:
cannam@233 83 class PluginDeletionNotifyAdapter : public PluginWrapper {
cannam@233 84 public:
cannam@233 85 PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
cannam@233 86 virtual ~PluginDeletionNotifyAdapter();
cannam@233 87 protected:
cannam@233 88 Impl *m_loader;
cannam@233 89 };
cannam@233 90
cannam@233 91 class InstanceCleaner {
cannam@233 92 public:
cannam@233 93 InstanceCleaner() : m_instance(0) { }
cannam@233 94 ~InstanceCleaner() { delete m_instance; }
cannam@233 95 void setInstance(PluginLoader *instance) { m_instance = instance; }
cannam@233 96 protected:
cannam@233 97 PluginLoader *m_instance;
cannam@233 98 };
cannam@233 99
cannam@233 100 virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
cannam@233 101
cannam@233 102 map<PluginKey, string> m_pluginLibraryNameMap;
cannam@233 103 bool m_allPluginsEnumerated;
cannam@233 104 void enumeratePlugins(PluginKey forPlugin = "");
cannam@233 105
cannam@233 106 map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
cannam@233 107 void generateTaxonomy();
cannam@233 108
cannam@233 109 map<Plugin *, void *> m_pluginLibraryHandleMap;
cannam@233 110
cannam@233 111 bool decomposePluginKey(PluginKey key,
cannam@233 112 string &libraryName, string &identifier);
cannam@233 113
cannam@233 114 static InstanceCleaner m_cleaner;
cannam@233 115 };
cannam@233 116
cannam@233 117 PluginLoader *
cannam@233 118 PluginLoader::m_instance = 0;
cannam@233 119
cannam@233 120 PluginLoader::Impl::InstanceCleaner
cannam@233 121 PluginLoader::Impl::m_cleaner;
cannam@233 122
cannam@233 123 PluginLoader::PluginLoader()
cannam@233 124 {
cannam@233 125 m_impl = new Impl();
cannam@233 126 }
cannam@233 127
cannam@233 128 PluginLoader::~PluginLoader()
cannam@233 129 {
cannam@233 130 delete m_impl;
cannam@233 131 }
cannam@233 132
cannam@233 133 PluginLoader *
cannam@233 134 PluginLoader::getInstance()
cannam@233 135 {
cannam@233 136 if (!m_instance) {
cannam@233 137 // The cleaner doesn't own the instance, because we leave the
cannam@233 138 // instance pointer in the base class for binary backwards
cannam@233 139 // compatibility reasons and to avoid waste
cannam@233 140 m_instance = new PluginLoader();
cannam@233 141 Impl::setInstanceToClean(m_instance);
cannam@233 142 }
cannam@233 143 return m_instance;
cannam@233 144 }
cannam@233 145
Chris@426 146 PluginLoader::PluginKeyList
cannam@233 147 PluginLoader::listPlugins()
cannam@233 148 {
cannam@233 149 return m_impl->listPlugins();
cannam@233 150 }
cannam@233 151
Chris@426 152 PluginLoader::PluginStaticDataList
Chris@426 153 PluginLoader::listPluginData()
Chris@426 154 {
Chris@426 155 return m_impl->listPluginData();
Chris@426 156 }
Chris@426 157
cannam@233 158 Plugin *
cannam@233 159 PluginLoader::loadPlugin(PluginKey key,
cannam@233 160 float inputSampleRate,
cannam@233 161 int adapterFlags)
cannam@233 162 {
cannam@233 163 return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
cannam@233 164 }
cannam@233 165
Chris@423 166 LoadResponse
Chris@423 167 PluginLoader::loadPlugin(LoadRequest req)
Chris@423 168 {
Chris@423 169 return m_impl->loadPlugin(req);
Chris@423 170 }
Chris@423 171
Chris@431 172 ConfigurationResponse
Chris@431 173 PluginLoader::configurePlugin(ConfigurationRequest req)
Chris@423 174 {
Chris@431 175 return m_impl->configurePlugin(req);
Chris@423 176 }
Chris@423 177
cannam@233 178 PluginLoader::PluginKey
cannam@233 179 PluginLoader::composePluginKey(string libraryName, string identifier)
cannam@233 180 {
cannam@233 181 return m_impl->composePluginKey(libraryName, identifier);
cannam@233 182 }
cannam@233 183
cannam@233 184 PluginLoader::PluginCategoryHierarchy
cannam@233 185 PluginLoader::getPluginCategory(PluginKey key)
cannam@233 186 {
cannam@233 187 return m_impl->getPluginCategory(key);
cannam@233 188 }
cannam@233 189
cannam@233 190 string
cannam@233 191 PluginLoader::getLibraryPathForPlugin(PluginKey key)
cannam@233 192 {
cannam@233 193 return m_impl->getLibraryPathForPlugin(key);
cannam@233 194 }
cannam@233 195
cannam@233 196 PluginLoader::Impl::Impl() :
cannam@233 197 m_allPluginsEnumerated(false)
cannam@233 198 {
cannam@233 199 }
cannam@233 200
cannam@233 201 PluginLoader::Impl::~Impl()
cannam@233 202 {
cannam@233 203 }
cannam@233 204
cannam@233 205 void
cannam@233 206 PluginLoader::Impl::setInstanceToClean(PluginLoader *instance)
cannam@233 207 {
cannam@233 208 m_cleaner.setInstance(instance);
cannam@233 209 }
cannam@233 210
Chris@426 211 PluginLoader::PluginKeyList
cannam@233 212 PluginLoader::Impl::listPlugins()
cannam@233 213 {
cannam@233 214 if (!m_allPluginsEnumerated) enumeratePlugins();
cannam@233 215
cannam@233 216 vector<PluginKey> plugins;
cannam@233 217 for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
cannam@233 218 mi != m_pluginLibraryNameMap.end(); ++mi) {
cannam@233 219 plugins.push_back(mi->first);
cannam@233 220 }
cannam@233 221
cannam@233 222 return plugins;
cannam@233 223 }
cannam@233 224
Chris@426 225 PluginLoader::PluginStaticDataList
Chris@426 226 PluginLoader::Impl::listPluginData()
Chris@426 227 {
Chris@426 228 PluginKeyList keys = listPlugins();
Chris@426 229 PluginStaticDataList dataList;
Chris@426 230
Chris@426 231 for (PluginKeyList::const_iterator ki = keys.begin(); ki != keys.end(); ++ki) {
Chris@426 232 string key = *ki;
Chris@426 233 Plugin *p = loadPlugin(key, 44100, 0);
Chris@426 234 if (p) {
Chris@426 235 string library = getLibraryPathForPlugin(key);
Chris@426 236 PluginCategoryHierarchy category = getPluginCategory(key);
Chris@426 237 dataList.push_back(PluginStaticData::fromPlugin(key, category, p));
Chris@426 238 }
Chris@426 239 delete p;
Chris@426 240 }
Chris@426 241
Chris@426 242 return dataList;
Chris@426 243 }
Chris@426 244
cannam@233 245 void
cannam@233 246 PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
cannam@233 247 {
cannam@233 248 string libraryName, identifier;
Chris@390 249 vector<string> fullPaths;
Chris@390 250
cannam@233 251 if (forPlugin != "") {
cannam@233 252 if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
cannam@233 253 std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
cannam@233 254 << forPlugin << "\" in enumerate" << std::endl;
cannam@233 255 return;
cannam@233 256 }
Chris@390 257 fullPaths = Files::listLibraryFilesMatching(libraryName);
Chris@390 258 } else {
Chris@390 259 fullPaths = Files::listLibraryFiles();
cannam@233 260 }
cannam@233 261
Chris@390 262 for (size_t i = 0; i < fullPaths.size(); ++i) {
cannam@233 263
Chris@390 264 string fullPath = fullPaths[i];
Chris@390 265 void *handle = Files::loadLibrary(fullPath);
Chris@390 266 if (!handle) continue;
cannam@233 267
Chris@390 268 VampGetPluginDescriptorFunction fn =
Chris@390 269 (VampGetPluginDescriptorFunction)Files::lookupInLibrary
Chris@390 270 (handle, "vampGetPluginDescriptor");
cannam@233 271
Chris@390 272 if (!fn) {
Chris@390 273 if (forPlugin != "") {
Chris@390 274 cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
cannam@295 275 << fullPath << "\"" << endl;
cannam@295 276 }
Chris@390 277 Files::unloadLibrary(handle);
Chris@390 278 continue;
Chris@390 279 }
cannam@233 280
Chris@390 281 int index = 0;
Chris@390 282 const VampPluginDescriptor *descriptor = 0;
Chris@390 283 bool found = false;
Chris@390 284
Chris@390 285 while ((descriptor = fn(VAMP_API_VERSION, index))) {
Chris@390 286 ++index;
Chris@390 287 if (identifier != "") {
Chris@390 288 if (descriptor->identifier != identifier) continue;
Chris@390 289 }
Chris@390 290 found = true;
Chris@390 291 PluginKey key = composePluginKey(fullPath, descriptor->identifier);
Chris@390 292 // std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
Chris@390 293 if (m_pluginLibraryNameMap.find(key) ==
Chris@390 294 m_pluginLibraryNameMap.end()) {
Chris@390 295 m_pluginLibraryNameMap[key] = fullPath;
Chris@390 296 }
cannam@233 297 }
Chris@390 298
Chris@390 299 if (!found && forPlugin != "") {
Chris@390 300 cerr << "Vamp::HostExt::PluginLoader: Plugin \""
Chris@390 301 << identifier << "\" not found in library \""
Chris@390 302 << fullPath << "\"" << endl;
Chris@390 303 }
Chris@390 304
Chris@390 305 Files::unloadLibrary(handle);
cannam@233 306 }
cannam@233 307
cannam@233 308 if (forPlugin == "") m_allPluginsEnumerated = true;
cannam@233 309 }
cannam@233 310
cannam@233 311 PluginLoader::PluginKey
cannam@233 312 PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
cannam@233 313 {
Chris@390 314 string basename = Files::lcBasename(libraryName);
cannam@233 315 return basename + ":" + identifier;
cannam@233 316 }
cannam@233 317
cannam@233 318 bool
cannam@233 319 PluginLoader::Impl::decomposePluginKey(PluginKey key,
cannam@233 320 string &libraryName,
cannam@233 321 string &identifier)
cannam@233 322 {
cannam@233 323 string::size_type ki = key.find(':');
cannam@233 324 if (ki == string::npos) {
cannam@233 325 return false;
cannam@233 326 }
cannam@233 327
cannam@233 328 libraryName = key.substr(0, ki);
cannam@233 329 identifier = key.substr(ki + 1);
cannam@233 330 return true;
cannam@233 331 }
cannam@233 332
cannam@233 333 PluginLoader::PluginCategoryHierarchy
cannam@233 334 PluginLoader::Impl::getPluginCategory(PluginKey plugin)
cannam@233 335 {
cannam@233 336 if (m_taxonomy.empty()) generateTaxonomy();
cannam@233 337 if (m_taxonomy.find(plugin) == m_taxonomy.end()) {
cannam@233 338 return PluginCategoryHierarchy();
cannam@233 339 }
cannam@233 340 return m_taxonomy[plugin];
cannam@233 341 }
cannam@233 342
cannam@233 343 string
cannam@233 344 PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
cannam@233 345 {
cannam@233 346 if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
cannam@233 347 if (m_allPluginsEnumerated) return "";
cannam@233 348 enumeratePlugins(plugin);
cannam@233 349 }
cannam@233 350 if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
cannam@233 351 return "";
cannam@233 352 }
cannam@233 353 return m_pluginLibraryNameMap[plugin];
cannam@233 354 }
cannam@233 355
cannam@233 356 Plugin *
cannam@233 357 PluginLoader::Impl::loadPlugin(PluginKey key,
cannam@233 358 float inputSampleRate, int adapterFlags)
cannam@233 359 {
cannam@233 360 string libname, identifier;
cannam@233 361 if (!decomposePluginKey(key, libname, identifier)) {
cannam@233 362 std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
cannam@233 363 << key << "\" in loadPlugin" << std::endl;
cannam@233 364 return 0;
cannam@233 365 }
cannam@233 366
cannam@233 367 string fullPath = getLibraryPathForPlugin(key);
cannam@293 368 if (fullPath == "") {
cannam@295 369 std::cerr << "Vamp::HostExt::PluginLoader: No library found in Vamp path for plugin \"" << key << "\"" << std::endl;
cannam@293 370 return 0;
cannam@293 371 }
cannam@233 372
Chris@390 373 void *handle = Files::loadLibrary(fullPath);
cannam@233 374 if (!handle) return 0;
cannam@233 375
cannam@233 376 VampGetPluginDescriptorFunction fn =
Chris@390 377 (VampGetPluginDescriptorFunction)Files::lookupInLibrary
cannam@233 378 (handle, "vampGetPluginDescriptor");
cannam@233 379
cannam@233 380 if (!fn) {
cannam@293 381 cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
cannam@293 382 << fullPath << "\"" << endl;
Chris@390 383 Files::unloadLibrary(handle);
cannam@233 384 return 0;
cannam@233 385 }
cannam@233 386
cannam@233 387 int index = 0;
cannam@233 388 const VampPluginDescriptor *descriptor = 0;
cannam@233 389
cannam@233 390 while ((descriptor = fn(VAMP_API_VERSION, index))) {
cannam@233 391
cannam@233 392 if (string(descriptor->identifier) == identifier) {
cannam@233 393
cannam@233 394 Vamp::PluginHostAdapter *plugin =
cannam@233 395 new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
cannam@233 396
cannam@233 397 Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
cannam@233 398
cannam@233 399 m_pluginLibraryHandleMap[adapter] = handle;
cannam@233 400
cannam@233 401 if (adapterFlags & ADAPT_INPUT_DOMAIN) {
cannam@233 402 if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
cannam@233 403 adapter = new PluginInputDomainAdapter(adapter);
cannam@233 404 }
cannam@233 405 }
cannam@233 406
cannam@233 407 if (adapterFlags & ADAPT_BUFFER_SIZE) {
cannam@233 408 adapter = new PluginBufferingAdapter(adapter);
cannam@233 409 }
cannam@233 410
cannam@233 411 if (adapterFlags & ADAPT_CHANNEL_COUNT) {
cannam@233 412 adapter = new PluginChannelAdapter(adapter);
cannam@233 413 }
cannam@233 414
cannam@233 415 return adapter;
cannam@233 416 }
cannam@233 417
cannam@233 418 ++index;
cannam@233 419 }
cannam@233 420
cannam@233 421 cerr << "Vamp::HostExt::PluginLoader: Plugin \""
cannam@233 422 << identifier << "\" not found in library \""
cannam@233 423 << fullPath << "\"" << endl;
cannam@233 424
cannam@233 425 return 0;
cannam@233 426 }
cannam@233 427
Chris@423 428 LoadResponse
Chris@423 429 PluginLoader::Impl::loadPlugin(LoadRequest req)
Chris@423 430 {
Chris@423 431 Plugin *plugin = loadPlugin(req.pluginKey,
Chris@423 432 req.inputSampleRate,
Chris@423 433 req.adapterFlags);
Chris@423 434 LoadResponse response;
Chris@425 435 response.plugin = plugin;
Chris@423 436 if (!plugin) return response;
Chris@423 437
Chris@423 438 response.plugin = plugin;
Chris@423 439 response.staticData = PluginStaticData::fromPlugin
Chris@423 440 (req.pluginKey,
Chris@423 441 getPluginCategory(req.pluginKey),
Chris@423 442 plugin);
Chris@423 443
Chris@423 444 int defaultChannels = 0;
Chris@423 445 if (plugin->getMinChannelCount() == plugin->getMaxChannelCount()) {
Chris@423 446 defaultChannels = plugin->getMinChannelCount();
Chris@423 447 }
Chris@423 448
Chris@423 449 response.defaultConfiguration = PluginConfiguration::fromPlugin
Chris@423 450 (plugin,
Chris@423 451 defaultChannels,
Chris@423 452 plugin->getPreferredStepSize(),
Chris@423 453 plugin->getPreferredBlockSize());
Chris@423 454
Chris@423 455 return response;
Chris@423 456 }
Chris@423 457
Chris@431 458 ConfigurationResponse
Chris@431 459 PluginLoader::Impl::configurePlugin(ConfigurationRequest req)
Chris@423 460 {
Chris@423 461 for (PluginConfiguration::ParameterMap::const_iterator i =
Chris@431 462 req.configuration.parameterValues.begin();
Chris@431 463 i != req.configuration.parameterValues.end(); ++i) {
Chris@431 464 req.plugin->setParameter(i->first, i->second);
Chris@423 465 }
Chris@423 466
Chris@431 467 if (req.configuration.currentProgram != "") {
Chris@431 468 req.plugin->selectProgram(req.configuration.currentProgram);
Chris@423 469 }
Chris@423 470
Chris@431 471 ConfigurationResponse response;
Chris@431 472
Chris@431 473 if (req.plugin->initialise(req.configuration.channelCount,
Chris@431 474 req.configuration.stepSize,
Chris@431 475 req.configuration.blockSize)) {
Chris@431 476 response.outputs = req.plugin->getOutputDescriptors();
Chris@423 477 }
Chris@431 478
Chris@431 479 return response;
Chris@423 480 }
Chris@423 481
cannam@233 482 void
cannam@233 483 PluginLoader::Impl::generateTaxonomy()
cannam@233 484 {
cannam@233 485 // cerr << "PluginLoader::Impl::generateTaxonomy" << endl;
cannam@233 486
cannam@233 487 vector<string> path = PluginHostAdapter::getPluginPath();
cannam@233 488 string libfragment = "/lib/";
cannam@233 489 vector<string> catpath;
cannam@233 490
cannam@233 491 string suffix = "cat";
cannam@233 492
cannam@233 493 for (vector<string>::iterator i = path.begin();
cannam@233 494 i != path.end(); ++i) {
cannam@233 495
cannam@233 496 // It doesn't matter that we're using literal forward-slash in
cannam@233 497 // this bit, as it's only relevant if the path contains
cannam@233 498 // "/lib/", which is only meaningful and only plausible on
cannam@233 499 // systems with forward-slash delimiters
cannam@233 500
cannam@233 501 string dir = *i;
cannam@233 502 string::size_type li = dir.find(libfragment);
cannam@233 503
cannam@233 504 if (li != string::npos) {
cannam@233 505 catpath.push_back
cannam@233 506 (dir.substr(0, li)
cannam@233 507 + "/share/"
cannam@233 508 + dir.substr(li + libfragment.length()));
cannam@233 509 }
cannam@233 510
cannam@233 511 catpath.push_back(dir);
cannam@233 512 }
cannam@233 513
cannam@233 514 char buffer[1024];
cannam@233 515
cannam@233 516 for (vector<string>::iterator i = catpath.begin();
cannam@233 517 i != catpath.end(); ++i) {
cannam@233 518
Chris@390 519 vector<string> files = Files::listFiles(*i, suffix);
cannam@233 520
cannam@233 521 for (vector<string>::iterator fi = files.begin();
cannam@233 522 fi != files.end(); ++fi) {
cannam@233 523
Chris@390 524 string filepath = Files::splicePath(*i, *fi);
cannam@233 525 ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
cannam@233 526
cannam@233 527 if (is.fail()) {
cannam@233 528 // cerr << "failed to open: " << filepath << endl;
cannam@233 529 continue;
cannam@233 530 }
cannam@233 531
cannam@233 532 // cerr << "opened: " << filepath << endl;
cannam@233 533
cannam@233 534 while (!!is.getline(buffer, 1024)) {
cannam@233 535
cannam@233 536 string line(buffer);
cannam@233 537
cannam@233 538 // cerr << "line = " << line << endl;
cannam@233 539
cannam@233 540 string::size_type di = line.find("::");
cannam@233 541 if (di == string::npos) continue;
cannam@233 542
cannam@233 543 string id = line.substr(0, di);
cannam@233 544 string encodedCat = line.substr(di + 2);
cannam@233 545
cannam@233 546 if (id.substr(0, 5) != "vamp:") continue;
cannam@233 547 id = id.substr(5);
cannam@233 548
cannam@233 549 while (encodedCat.length() >= 1 &&
cannam@233 550 encodedCat[encodedCat.length()-1] == '\r') {
cannam@233 551 encodedCat = encodedCat.substr(0, encodedCat.length()-1);
cannam@233 552 }
cannam@233 553
cannam@233 554 // cerr << "id = " << id << ", cat = " << encodedCat << endl;
cannam@233 555
cannam@233 556 PluginCategoryHierarchy category;
cannam@233 557 string::size_type ai;
cannam@233 558 while ((ai = encodedCat.find(" > ")) != string::npos) {
cannam@233 559 category.push_back(encodedCat.substr(0, ai));
cannam@233 560 encodedCat = encodedCat.substr(ai + 3);
cannam@233 561 }
cannam@233 562 if (encodedCat != "") category.push_back(encodedCat);
cannam@233 563
cannam@233 564 m_taxonomy[id] = category;
cannam@233 565 }
cannam@233 566 }
cannam@233 567 }
cannam@233 568 }
cannam@233 569
cannam@233 570 void
cannam@233 571 PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
cannam@233 572 {
cannam@233 573 void *handle = m_pluginLibraryHandleMap[adapter];
Chris@390 574 if (handle) Files::unloadLibrary(handle);
cannam@233 575 m_pluginLibraryHandleMap.erase(adapter);
cannam@233 576 }
cannam@233 577
cannam@233 578 PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
cannam@233 579 Impl *loader) :
cannam@233 580 PluginWrapper(plugin),
cannam@233 581 m_loader(loader)
cannam@233 582 {
cannam@233 583 }
cannam@233 584
cannam@233 585 PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
cannam@233 586 {
cannam@233 587 // We need to delete the plugin before calling pluginDeleted, as
cannam@233 588 // the delete call may require calling through to the descriptor
cannam@233 589 // (for e.g. cleanup) but pluginDeleted may unload the required
cannam@233 590 // library for the call. To prevent a double deletion when our
cannam@233 591 // parent's destructor runs (after this one), be sure to set
cannam@233 592 // m_plugin to 0 after deletion.
cannam@233 593 delete m_plugin;
cannam@233 594 m_plugin = 0;
cannam@233 595
cannam@233 596 if (m_loader) m_loader->pluginDeleted(this);
cannam@233 597 }
cannam@233 598
cannam@233 599 }
cannam@233 600
cannam@233 601 }
cannam@263 602
cannam@263 603 _VAMP_SDK_HOSTSPACE_END(PluginLoader.cpp)
cannam@263 604