LADSPAPluginFactory.cpp

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

Generated on Wed Feb 20 15:45:26 2008 for SonicVisualiser by  doxygen 1.5.1