svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 00008 This program is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU General Public License as 00010 published by the Free Software Foundation; either version 2 of the 00011 License, or (at your option) any later version. See the file 00012 COPYING included with this distribution for more information. 00013 */ 00014 00015 /* 00016 This is a modified version of a source file from the 00017 Rosegarden MIDI and audio sequencer and notation editor. 00018 This file copyright 2000-2006 Chris Cannam and Richard Bown. 00019 */ 00020 00021 #include "LADSPAPluginFactory.h" 00022 #include <iostream> 00023 00024 #include <QDir> 00025 #include <QFile> 00026 #include <QTextStream> 00027 00028 #include <cmath> 00029 00030 #include "LADSPAPluginInstance.h" 00031 #include "PluginIdentifier.h" 00032 00033 #include "system/System.h" 00034 #include "base/Preferences.h" 00035 #include "base/Profiler.h" 00036 00037 //#define DEBUG_LADSPA_PLUGIN_FACTORY 1 00038 00039 #ifdef HAVE_LRDF 00040 #include "lrdf.h" 00041 #endif // HAVE_LRDF 00042 00043 00044 LADSPAPluginFactory::LADSPAPluginFactory() 00045 { 00046 #ifdef HAVE_LRDF 00047 lrdf_init(); 00048 #endif 00049 } 00050 00051 LADSPAPluginFactory::~LADSPAPluginFactory() 00052 { 00053 for (std::set<RealTimePluginInstance *>::iterator i = m_instances.begin(); 00054 i != m_instances.end(); ++i) { 00055 (*i)->setFactory(0); 00056 delete *i; 00057 } 00058 m_instances.clear(); 00059 unloadUnusedLibraries(); 00060 00061 #ifdef HAVE_LRDF 00062 lrdf_cleanup(); 00063 #endif // HAVE_LRDF 00064 } 00065 00066 const std::vector<QString> & 00067 LADSPAPluginFactory::getPluginIdentifiers() const 00068 { 00069 return m_identifiers; 00070 } 00071 00072 void 00073 LADSPAPluginFactory::enumeratePlugins(std::vector<QString> &list) 00074 { 00075 Profiler profiler("LADSPAPluginFactory::enumeratePlugins"); 00076 00077 for (std::vector<QString>::iterator i = m_identifiers.begin(); 00078 i != m_identifiers.end(); ++i) { 00079 00080 const LADSPA_Descriptor *descriptor = getLADSPADescriptor(*i); 00081 00082 if (!descriptor) { 00083 cerr << "WARNING: LADSPAPluginFactory::enumeratePlugins: couldn't get descriptor for identifier " << *i << endl; 00084 continue; 00085 } 00086 00087 list.push_back(*i); 00088 list.push_back(descriptor->Name); 00089 list.push_back(QString("%1").arg(descriptor->UniqueID)); 00090 list.push_back(descriptor->Label); 00091 list.push_back(descriptor->Maker); 00092 list.push_back(descriptor->Copyright); 00093 list.push_back("false"); // is synth 00094 list.push_back("false"); // is grouped 00095 00096 if (m_taxonomy.find(*i) != m_taxonomy.end() && m_taxonomy[*i] != "") { 00097 // cerr << "LADSPAPluginFactory: cat for " << *i << " found in taxonomy as " << m_taxonomy[descriptor->UniqueID] << endl; 00098 list.push_back(m_taxonomy[*i]); 00099 } else { 00100 list.push_back(""); 00101 // cerr << "LADSPAPluginFactory: cat for " << *i << " not found (despite having " << m_fallbackCategories.size() << " fallbacks)" << endl; 00102 00103 } 00104 00105 list.push_back(QString("%1").arg(descriptor->PortCount)); 00106 00107 for (unsigned long p = 0; p < descriptor->PortCount; ++p) { 00108 00109 int type = 0; 00110 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) { 00111 type |= PortType::Control; 00112 } else { 00113 type |= PortType::Audio; 00114 } 00115 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) { 00116 type |= PortType::Input; 00117 } else { 00118 type |= PortType::Output; 00119 } 00120 00121 list.push_back(QString("%1").arg(p)); 00122 list.push_back(descriptor->PortNames[p]); 00123 list.push_back(QString("%1").arg(type)); 00124 list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p))); 00125 list.push_back(QString("%1").arg(getPortMinimum(descriptor, p))); 00126 list.push_back(QString("%1").arg(getPortMaximum(descriptor, p))); 00127 list.push_back(QString("%1").arg(getPortDefault(descriptor, p))); 00128 } 00129 } 00130 00131 unloadUnusedLibraries(); 00132 } 00133 00134 const RealTimePluginDescriptor * 00135 LADSPAPluginFactory::getPluginDescriptor(QString identifier) const 00136 { 00137 std::map<QString, RealTimePluginDescriptor *>::const_iterator i = 00138 m_rtDescriptors.find(identifier); 00139 00140 if (i != m_rtDescriptors.end()) { 00141 return i->second; 00142 } 00143 00144 return 0; 00145 } 00146 00147 float 00148 LADSPAPluginFactory::getPortMinimum(const LADSPA_Descriptor *descriptor, int port) 00149 { 00150 LADSPA_PortRangeHintDescriptor d = 00151 descriptor->PortRangeHints[port].HintDescriptor; 00152 00153 float minimum = 0.0; 00154 00155 if (LADSPA_IS_HINT_BOUNDED_BELOW(d)) { 00156 float lb = descriptor->PortRangeHints[port].LowerBound; 00157 minimum = lb; 00158 } else if (LADSPA_IS_HINT_BOUNDED_ABOVE(d)) { 00159 float ub = descriptor->PortRangeHints[port].UpperBound; 00160 minimum = std::min(0.0, ub - 1.0); 00161 } 00162 00163 if (LADSPA_IS_HINT_SAMPLE_RATE(d)) { 00164 minimum *= m_sampleRate; 00165 } 00166 00167 if (LADSPA_IS_HINT_LOGARITHMIC(d)) { 00168 if (minimum == 0.f) minimum = 1.f; 00169 } 00170 00171 return minimum; 00172 } 00173 00174 float 00175 LADSPAPluginFactory::getPortMaximum(const LADSPA_Descriptor *descriptor, int port) 00176 { 00177 LADSPA_PortRangeHintDescriptor d = 00178 descriptor->PortRangeHints[port].HintDescriptor; 00179 00180 float maximum = 1.0; 00181 00182 if (LADSPA_IS_HINT_BOUNDED_ABOVE(d)) { 00183 float ub = descriptor->PortRangeHints[port].UpperBound; 00184 maximum = ub; 00185 } else { 00186 float lb = descriptor->PortRangeHints[port].LowerBound; 00187 maximum = lb + 1.0; 00188 } 00189 00190 if (LADSPA_IS_HINT_SAMPLE_RATE(d)) { 00191 maximum *= m_sampleRate; 00192 } 00193 00194 return maximum; 00195 } 00196 00197 float 00198 LADSPAPluginFactory::getPortDefault(const LADSPA_Descriptor *descriptor, int port) 00199 { 00200 float minimum = getPortMinimum(descriptor, port); 00201 float maximum = getPortMaximum(descriptor, port); 00202 float deft; 00203 00204 if (m_portDefaults.find(descriptor->UniqueID) != 00205 m_portDefaults.end()) { 00206 if (m_portDefaults[descriptor->UniqueID].find(port) != 00207 m_portDefaults[descriptor->UniqueID].end()) { 00208 00209 deft = m_portDefaults[descriptor->UniqueID][port]; 00210 if (deft < minimum) deft = minimum; 00211 if (deft > maximum) deft = maximum; 00212 return deft; 00213 } 00214 } 00215 00216 LADSPA_PortRangeHintDescriptor d = 00217 descriptor->PortRangeHints[port].HintDescriptor; 00218 00219 bool logarithmic = LADSPA_IS_HINT_LOGARITHMIC(d); 00220 00221 float logmin = 0, logmax = 0; 00222 if (logarithmic) { 00223 float thresh = powf(10, -10); 00224 if (minimum < thresh) logmin = -10; 00225 else logmin = log10f(minimum); 00226 if (maximum < thresh) logmax = -10; 00227 else logmax = log10f(maximum); 00228 } 00229 00230 // SVDEBUG << "LADSPAPluginFactory::getPortDefault: hint = " << d << endl; 00231 00232 if (!LADSPA_IS_HINT_HAS_DEFAULT(d)) { 00233 00234 deft = minimum; 00235 00236 } else if (LADSPA_IS_HINT_DEFAULT_MINIMUM(d)) { 00237 00238 deft = minimum; 00239 00240 } else if (LADSPA_IS_HINT_DEFAULT_LOW(d)) { 00241 00242 if (logarithmic) { 00243 deft = powf(10, logmin * 0.75 + logmax * 0.25); 00244 } else { 00245 deft = minimum * 0.75 + maximum * 0.25; 00246 } 00247 00248 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(d)) { 00249 00250 if (logarithmic) { 00251 deft = powf(10, logmin * 0.5 + logmax * 0.5); 00252 } else { 00253 deft = minimum * 0.5 + maximum * 0.5; 00254 } 00255 00256 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(d)) { 00257 00258 if (logarithmic) { 00259 deft = powf(10, logmin * 0.25 + logmax * 0.75); 00260 } else { 00261 deft = minimum * 0.25 + maximum * 0.75; 00262 } 00263 00264 } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(d)) { 00265 00266 deft = maximum; 00267 00268 } else if (LADSPA_IS_HINT_DEFAULT_0(d)) { 00269 00270 deft = 0.0; 00271 00272 } else if (LADSPA_IS_HINT_DEFAULT_1(d)) { 00273 00274 deft = 1.0; 00275 00276 } else if (LADSPA_IS_HINT_DEFAULT_100(d)) { 00277 00278 deft = 100.0; 00279 00280 } else if (LADSPA_IS_HINT_DEFAULT_440(d)) { 00281 00282 // deft = 440.0; 00283 deft = Preferences::getInstance()->getTuningFrequency(); 00284 00285 } else { 00286 00287 deft = minimum; 00288 } 00289 00291 //so it would happen twice if we did it here -- and e.g. DEFAULT_440 00292 //doesn't want to be multiplied by the rate either 00293 00294 // if (LADSPA_IS_HINT_SAMPLE_RATE(d)) { 00295 // deft *= m_sampleRate; 00296 // } 00297 00298 return deft; 00299 } 00300 00301 float 00302 LADSPAPluginFactory::getPortQuantization(const LADSPA_Descriptor *descriptor, int port) 00303 { 00304 int displayHint = getPortDisplayHint(descriptor, port); 00305 if (displayHint & PortHint::Toggled) { 00306 return lrintf(getPortMaximum(descriptor, port)) - 00307 lrintf(getPortMinimum(descriptor, port)); 00308 } 00309 if (displayHint & PortHint::Integer) { 00310 return 1.0; 00311 } 00312 return 0.0; 00313 } 00314 00315 int 00316 LADSPAPluginFactory::getPortDisplayHint(const LADSPA_Descriptor *descriptor, int port) 00317 { 00318 LADSPA_PortRangeHintDescriptor d = 00319 descriptor->PortRangeHints[port].HintDescriptor; 00320 int hint = PortHint::NoHint; 00321 00322 if (LADSPA_IS_HINT_TOGGLED(d)) hint |= PortHint::Toggled; 00323 if (LADSPA_IS_HINT_INTEGER(d)) hint |= PortHint::Integer; 00324 if (LADSPA_IS_HINT_LOGARITHMIC(d)) hint |= PortHint::Logarithmic; 00325 00326 return hint; 00327 } 00328 00329 00330 RealTimePluginInstance * 00331 LADSPAPluginFactory::instantiatePlugin(QString identifier, 00332 int instrument, 00333 int position, 00334 unsigned int sampleRate, 00335 unsigned int blockSize, 00336 unsigned int channels) 00337 { 00338 Profiler profiler("LADSPAPluginFactory::instantiatePlugin"); 00339 00340 const LADSPA_Descriptor *descriptor = getLADSPADescriptor(identifier); 00341 00342 if (descriptor) { 00343 00344 LADSPAPluginInstance *instance = 00345 new LADSPAPluginInstance 00346 (this, instrument, identifier, position, sampleRate, blockSize, channels, 00347 descriptor); 00348 00349 m_instances.insert(instance); 00350 00351 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00352 SVDEBUG << "LADSPAPluginFactory::instantiatePlugin(" 00353 << identifier << ": now have " << m_instances.size() << " instances" << endl; 00354 #endif 00355 00356 return instance; 00357 } 00358 00359 return 0; 00360 } 00361 00362 void 00363 LADSPAPluginFactory::releasePlugin(RealTimePluginInstance *instance, 00364 QString identifier) 00365 { 00366 Profiler profiler("LADSPAPluginFactory::releasePlugin"); 00367 00368 if (m_instances.find(instance) == m_instances.end()) { 00369 cerr << "WARNING: LADSPAPluginFactory::releasePlugin: Not one of mine!" 00370 << endl; 00371 return; 00372 } 00373 00374 QString type, soname, label; 00375 PluginIdentifier::parseIdentifier(identifier, type, soname, label); 00376 00377 m_instances.erase(instance); 00378 00379 bool stillInUse = false; 00380 00381 for (std::set<RealTimePluginInstance *>::iterator ii = m_instances.begin(); 00382 ii != m_instances.end(); ++ii) { 00383 QString itype, isoname, ilabel; 00384 PluginIdentifier::parseIdentifier((*ii)->getPluginIdentifier(), itype, isoname, ilabel); 00385 if (isoname == soname) { 00386 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00387 SVDEBUG << "LADSPAPluginFactory::releasePlugin: dll " << soname << " is still in use for plugin " << ilabel << endl; 00388 #endif 00389 stillInUse = true; 00390 break; 00391 } 00392 } 00393 00394 if (!stillInUse) { 00395 if (soname != PluginIdentifier::BUILTIN_PLUGIN_SONAME) { 00396 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00397 SVDEBUG << "LADSPAPluginFactory::releasePlugin: dll " << soname << " no longer in use, unloading" << endl; 00398 #endif 00399 unloadLibrary(soname); 00400 } 00401 } 00402 00403 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00404 SVDEBUG << "LADSPAPluginFactory::releasePlugin(" 00405 << identifier << ": now have " << m_instances.size() << " instances" << endl; 00406 #endif 00407 } 00408 00409 const LADSPA_Descriptor * 00410 LADSPAPluginFactory::getLADSPADescriptor(QString identifier) 00411 { 00412 QString type, soname, label; 00413 PluginIdentifier::parseIdentifier(identifier, type, soname, label); 00414 00415 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) { 00416 loadLibrary(soname); 00417 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) { 00418 cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: loadLibrary failed for " << soname << endl; 00419 return 0; 00420 } 00421 } 00422 00423 void *libraryHandle = m_libraryHandles[soname]; 00424 00425 LADSPA_Descriptor_Function fn = (LADSPA_Descriptor_Function) 00426 DLSYM(libraryHandle, "ladspa_descriptor"); 00427 00428 if (!fn) { 00429 cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: No descriptor function in library " << soname << endl; 00430 return 0; 00431 } 00432 00433 const LADSPA_Descriptor *descriptor = 0; 00434 00435 int index = 0; 00436 while ((descriptor = fn(index))) { 00437 if (descriptor->Label == label) return descriptor; 00438 ++index; 00439 } 00440 00441 cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: No such plugin as " << label << " in library " << soname << endl; 00442 00443 return 0; 00444 } 00445 00446 void 00447 LADSPAPluginFactory::loadLibrary(QString soName) 00448 { 00449 void *libraryHandle = DLOPEN(soName, RTLD_NOW); 00450 if (libraryHandle) { 00451 m_libraryHandles[soName] = libraryHandle; 00452 SVDEBUG << "LADSPAPluginFactory::loadLibrary: Loaded library \"" << soName << "\"" << endl; 00453 return; 00454 } 00455 00456 if (QFileInfo(soName).exists()) { 00457 DLERROR(); 00458 cerr << "LADSPAPluginFactory::loadLibrary: Library \"" << soName << "\" exists, but failed to load it" << endl; 00459 return; 00460 } 00461 00462 std::vector<QString> pathList = getPluginPath(); 00463 00464 QString fileName = QFile(soName).fileName(); 00465 QString base = QFileInfo(soName).baseName(); 00466 00467 for (std::vector<QString>::iterator i = pathList.begin(); 00468 i != pathList.end(); ++i) { 00469 00470 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00471 SVDEBUG << "Looking at: " << (*i) << endl; 00472 #endif 00473 00474 QDir dir(*i, PLUGIN_GLOB, 00475 QDir::Name | QDir::IgnoreCase, 00476 QDir::Files | QDir::Readable); 00477 00478 if (QFileInfo(dir.filePath(fileName)).exists()) { 00479 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00480 cerr << "Loading: " << fileName << endl; 00481 #endif 00482 libraryHandle = DLOPEN(dir.filePath(fileName), RTLD_NOW); 00483 if (libraryHandle) { 00484 m_libraryHandles[soName] = libraryHandle; 00485 return; 00486 } 00487 } 00488 00489 for (unsigned int j = 0; j < dir.count(); ++j) { 00490 QString file = dir.filePath(dir[j]); 00491 if (QFileInfo(file).baseName() == base) { 00492 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY 00493 cerr << "Loading: " << file << endl; 00494 #endif 00495 libraryHandle = DLOPEN(file, RTLD_NOW); 00496 if (libraryHandle) { 00497 m_libraryHandles[soName] = libraryHandle; 00498 return; 00499 } 00500 } 00501 } 00502 } 00503 00504 cerr << "LADSPAPluginFactory::loadLibrary: Failed to locate plugin library \"" << soName << "\"" << endl; 00505 } 00506 00507 void 00508 LADSPAPluginFactory::unloadLibrary(QString soName) 00509 { 00510 LibraryHandleMap::iterator li = m_libraryHandles.find(soName); 00511 if (li != m_libraryHandles.end()) { 00512 // SVDEBUG << "unloading " << soname << endl; 00513 DLCLOSE(m_libraryHandles[soName]); 00514 m_libraryHandles.erase(li); 00515 } 00516 } 00517 00518 void 00519 LADSPAPluginFactory::unloadUnusedLibraries() 00520 { 00521 std::vector<QString> toUnload; 00522 00523 for (LibraryHandleMap::iterator i = m_libraryHandles.begin(); 00524 i != m_libraryHandles.end(); ++i) { 00525 00526 bool stillInUse = false; 00527 00528 for (std::set<RealTimePluginInstance *>::iterator ii = m_instances.begin(); 00529 ii != m_instances.end(); ++ii) { 00530 00531 QString itype, isoname, ilabel; 00532 PluginIdentifier::parseIdentifier((*ii)->getPluginIdentifier(), itype, isoname, ilabel); 00533 if (isoname == i->first) { 00534 stillInUse = true; 00535 break; 00536 } 00537 } 00538 00539 if (!stillInUse) toUnload.push_back(i->first); 00540 } 00541 00542 for (std::vector<QString>::iterator i = toUnload.begin(); 00543 i != toUnload.end(); ++i) { 00544 if (*i != PluginIdentifier::BUILTIN_PLUGIN_SONAME) { 00545 unloadLibrary(*i); 00546 } 00547 } 00548 } 00549 00550 00551 // It is only later, after they've gone, 00552 // I realize they have delivered a letter. 00553 // It's a letter from my wife. "What are you doing 00554 // there?" my wife asks. "Are you drinking?" 00555 // I study the postmark for hours. Then it, too, begins to fade. 00556 // I hope someday to forget all this. 00557 00558 00559 std::vector<QString> 00560 LADSPAPluginFactory::getPluginPath() 00561 { 00562 std::vector<QString> pathList; 00563 std::string path; 00564 00565 char *cpath = getenv("LADSPA_PATH"); 00566 if (cpath) path = cpath; 00567 00568 if (path == "") { 00569 00570 path = DEFAULT_LADSPA_PATH; 00571 00572 char *home = getenv("HOME"); 00573 if (home) { 00574 std::string::size_type f; 00575 while ((f = path.find("$HOME")) != std::string::npos && 00576 f < path.length()) { 00577 path.replace(f, 5, home); 00578 } 00579 } 00580 00581 #ifdef _WIN32 00582 char *pfiles = getenv("ProgramFiles"); 00583 if (!pfiles) pfiles = "C:\\Program Files"; 00584 { 00585 std::string::size_type f; 00586 while ((f = path.find("%ProgramFiles%")) != std::string::npos && 00587 f < path.length()) { 00588 path.replace(f, 14, pfiles); 00589 } 00590 } 00591 #endif 00592 } 00593 00594 std::string::size_type index = 0, newindex = 0; 00595 00596 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) { 00597 pathList.push_back(path.substr(index, newindex - index).c_str()); 00598 index = newindex + 1; 00599 } 00600 00601 pathList.push_back(path.substr(index).c_str()); 00602 00603 return pathList; 00604 } 00605 00606 00607 std::vector<QString> 00608 LADSPAPluginFactory::getLRDFPath(QString &baseUri) 00609 { 00610 std::vector<QString> lrdfPaths; 00611 00612 #ifdef HAVE_LRDF 00613 std::vector<QString> pathList = getPluginPath(); 00614 00615 lrdfPaths.push_back("/usr/local/share/ladspa/rdf"); 00616 lrdfPaths.push_back("/usr/share/ladspa/rdf"); 00617 00618 for (std::vector<QString>::iterator i = pathList.begin(); 00619 i != pathList.end(); ++i) { 00620 lrdfPaths.push_back(*i + "/rdf"); 00621 } 00622 00623 baseUri = LADSPA_BASE; 00624 #else 00625 baseUri = ""; 00626 #endif 00627 00628 return lrdfPaths; 00629 } 00630 00631 void 00632 LADSPAPluginFactory::discoverPlugins() 00633 { 00634 Profiler profiler("LADSPAPluginFactory::discoverPlugins"); 00635 00636 std::vector<QString> pathList = getPluginPath(); 00637 00638 // SVDEBUG << "LADSPAPluginFactory::discoverPlugins - " 00639 // << "discovering plugins; path is "; 00640 // for (std::vector<QString>::iterator i = pathList.begin(); 00641 // i != pathList.end(); ++i) { 00642 // SVDEBUG << "[" << i-<< "] "; 00643 // } 00644 // SVDEBUG << endl; 00645 00646 #ifdef HAVE_LRDF 00647 // read the description files 00648 // 00649 QString baseUri; 00650 std::vector<QString> lrdfPaths = getLRDFPath(baseUri); 00651 00652 bool haveSomething = false; 00653 00654 for (size_t i = 0; i < lrdfPaths.size(); ++i) { 00655 QDir dir(lrdfPaths[i], "*.rdf;*.rdfs"); 00656 for (unsigned int j = 0; j < dir.count(); ++j) { 00657 if (!lrdf_read_file(QString("file:" + lrdfPaths[i] + "/" + dir[j]).toStdString().c_str())) { 00658 // cerr << "LADSPAPluginFactory: read RDF file " << (lrdfPaths[i] + "/" + dir[j]) << endl; 00659 haveSomething = true; 00660 } 00661 } 00662 } 00663 00664 if (haveSomething) { 00665 generateTaxonomy(baseUri + "Plugin", ""); 00666 } 00667 #endif // HAVE_LRDF 00668 00669 generateFallbackCategories(); 00670 00671 for (std::vector<QString>::iterator i = pathList.begin(); 00672 i != pathList.end(); ++i) { 00673 00674 QDir pluginDir(*i, PLUGIN_GLOB); 00675 00676 for (unsigned int j = 0; j < pluginDir.count(); ++j) { 00677 discoverPluginsFrom(QString("%1/%2").arg(*i).arg(pluginDir[j])); 00678 } 00679 } 00680 } 00681 00682 void 00683 LADSPAPluginFactory::discoverPluginsFrom(QString soname) 00684 { 00685 void *libraryHandle = DLOPEN(soname, RTLD_LAZY); 00686 00687 if (!libraryHandle) { 00688 cerr << "WARNING: LADSPAPluginFactory::discoverPlugins: couldn't load plugin library " 00689 << soname << " - " << DLERROR() << endl; 00690 return; 00691 } 00692 00693 LADSPA_Descriptor_Function fn = (LADSPA_Descriptor_Function) 00694 DLSYM(libraryHandle, "ladspa_descriptor"); 00695 00696 if (!fn) { 00697 cerr << "WARNING: LADSPAPluginFactory::discoverPlugins: No descriptor function in " << soname << endl; 00698 return; 00699 } 00700 00701 const LADSPA_Descriptor *descriptor = 0; 00702 00703 int index = 0; 00704 while ((descriptor = fn(index))) { 00705 00706 RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor; 00707 rtd->name = descriptor->Name; 00708 rtd->label = descriptor->Label; 00709 rtd->maker = descriptor->Maker; 00710 rtd->copyright = descriptor->Copyright; 00711 rtd->category = ""; 00712 rtd->isSynth = false; 00713 rtd->parameterCount = 0; 00714 rtd->audioInputPortCount = 0; 00715 rtd->audioOutputPortCount = 0; 00716 rtd->controlOutputPortCount = 0; 00717 00718 QString identifier = PluginIdentifier::createIdentifier 00719 ("ladspa", soname, descriptor->Label); 00720 00721 #ifdef HAVE_LRDF 00722 char *def_uri = 0; 00723 lrdf_defaults *defs = 0; 00724 00725 if (m_lrdfTaxonomy[descriptor->UniqueID] != "") { 00726 m_taxonomy[identifier] = m_lrdfTaxonomy[descriptor->UniqueID]; 00727 // cerr << "set id \"" << identifier << "\" to cat \"" << m_taxonomy[identifier] << "\" from LRDF" << endl; 00728 // cout << identifier << "::" << m_taxonomy[identifier] << endl; 00729 } 00730 00731 QString category = m_taxonomy[identifier]; 00732 00733 if (category == "") { 00734 std::string name = rtd->name; 00735 if (name.length() > 4 && 00736 name.substr(name.length() - 4) == " VST") { 00737 category = "VST effects"; 00738 m_taxonomy[identifier] = category; 00739 } 00740 } 00741 00742 rtd->category = category.toStdString(); 00743 00744 // cerr << "Plugin id is " << descriptor->UniqueID 00745 // << ", category is \"" << (category ? category : QString("(none)")) 00746 // << "\", name is " << descriptor->Name 00747 // << ", label is " << descriptor->Label 00748 // << endl; 00749 00750 def_uri = lrdf_get_default_uri(descriptor->UniqueID); 00751 if (def_uri) { 00752 defs = lrdf_get_setting_values(def_uri); 00753 } 00754 00755 unsigned int controlPortNumber = 1; 00756 00757 for (unsigned long i = 0; i < descriptor->PortCount; i++) { 00758 00759 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) { 00760 00761 if (def_uri && defs) { 00762 00763 for (unsigned int j = 0; j < defs->count; j++) { 00764 if (defs->items[j].pid == controlPortNumber) { 00765 // cerr << "Default for this port (" << defs->items[j].pid << ", " << defs->items[j].label << ") is " << defs->items[j].value << "; applying this to port number " << i << " with name " << descriptor->PortNames[i] << endl; 00766 m_portDefaults[descriptor->UniqueID][i] = 00767 defs->items[j].value; 00768 } 00769 } 00770 } 00771 00772 ++controlPortNumber; 00773 } 00774 } 00775 #endif // HAVE_LRDF 00776 00777 for (unsigned long i = 0; i < descriptor->PortCount; i++) { 00778 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) { 00779 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) { 00780 ++rtd->parameterCount; 00781 } else { 00782 if (strcmp(descriptor->PortNames[i], "latency") && 00783 strcmp(descriptor->PortNames[i], "_latency")) { 00784 ++rtd->controlOutputPortCount; 00785 rtd->controlOutputPortNames.push_back 00786 (descriptor->PortNames[i]); 00787 } 00788 } 00789 } else { 00790 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) { 00791 ++rtd->audioInputPortCount; 00792 } else if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[i])) { 00793 ++rtd->audioOutputPortCount; 00794 } 00795 } 00796 } 00797 00798 m_identifiers.push_back(identifier); 00799 00800 m_rtDescriptors[identifier] = rtd; 00801 00802 ++index; 00803 } 00804 00805 if (DLCLOSE(libraryHandle) != 0) { 00806 cerr << "WARNING: LADSPAPluginFactory::discoverPlugins - can't unload " << libraryHandle << endl; 00807 return; 00808 } 00809 } 00810 00811 void 00812 LADSPAPluginFactory::generateFallbackCategories() 00813 { 00814 std::vector<QString> pluginPath = getPluginPath(); 00815 std::vector<QString> path; 00816 00817 for (size_t i = 0; i < pluginPath.size(); ++i) { 00818 if (pluginPath[i].contains("/lib/")) { 00819 QString p(pluginPath[i]); 00820 path.push_back(p); 00821 p.replace("/lib/", "/share/"); 00822 path.push_back(p); 00823 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: path element " << p << endl; 00824 } 00825 path.push_back(pluginPath[i]); 00826 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: path element " << pluginPath[i] << endl; 00827 } 00828 00829 for (size_t i = 0; i < path.size(); ++i) { 00830 00831 QDir dir(path[i], "*.cat"); 00832 00833 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl; 00834 for (unsigned int j = 0; j < dir.count(); ++j) { 00835 00836 QFile file(path[i] + "/" + dir[j]); 00837 00838 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl; 00839 00840 if (file.open(QIODevice::ReadOnly)) { 00841 // cerr << "...opened" << endl; 00842 QTextStream stream(&file); 00843 QString line; 00844 00845 while (!stream.atEnd()) { 00846 line = stream.readLine(); 00847 // cerr << "line is: \"" << line << "\"" << endl; 00848 QString id = PluginIdentifier::canonicalise 00849 (line.section("::", 0, 0)); 00850 QString cat = line.section("::", 1, 1); 00851 m_taxonomy[id] = cat; 00852 // cerr << "set id \"" << id << "\" to cat \"" << cat << "\"" << endl; 00853 } 00854 } 00855 } 00856 } 00857 } 00858 00859 void 00860 LADSPAPluginFactory::generateTaxonomy(QString uri, QString base) 00861 { 00862 #ifdef HAVE_LRDF 00863 lrdf_uris *uris = lrdf_get_instances(uri.toStdString().c_str()); 00864 00865 if (uris != NULL) { 00866 for (unsigned int i = 0; i < uris->count; ++i) { 00867 m_lrdfTaxonomy[lrdf_get_uid(uris->items[i])] = base; 00868 } 00869 lrdf_free_uris(uris); 00870 } 00871 00872 uris = lrdf_get_subclasses(uri.toStdString().c_str()); 00873 00874 if (uris != NULL) { 00875 for (unsigned int i = 0; i < uris->count; ++i) { 00876 char *label = lrdf_get_label(uris->items[i]); 00877 generateTaxonomy(uris->items[i], 00878 base + (base.length() > 0 ? " > " : "") + label); 00879 } 00880 lrdf_free_uris(uris); 00881 } 00882 #else 00883 // avoid unused parameter 00884 (void)uri; 00885 (void)base; 00886 #endif 00887 } 00888 00889 QString 00890 LADSPAPluginFactory::getPluginCategory(QString identifier) 00891 { 00892 return m_taxonomy[identifier]; 00893 } 00894