DSSIPluginFactory.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.
00019 */
00020 
00021 #include "DSSIPluginFactory.h"
00022 #include <iostream>
00023 
00024 #include <QString>
00025 
00026 #include "DSSIPluginInstance.h"
00027 #include "PluginIdentifier.h"
00028 
00030 #include "plugin/plugins/SamplePlayer.h"
00031 
00032 #include "system/System.h"
00033 
00034 #ifdef HAVE_LRDF
00035 #include "lrdf.h"
00036 #endif // HAVE_LRDF
00037 
00038 
00039 DSSIPluginFactory::DSSIPluginFactory() :
00040     LADSPAPluginFactory()
00041 {
00042     m_hostDescriptor.DSSI_API_Version = 2;
00043     m_hostDescriptor.request_transport_information = NULL;
00044     m_hostDescriptor.request_midi_send = DSSIPluginInstance::requestMidiSend;
00045     m_hostDescriptor.request_non_rt_thread = DSSIPluginInstance::requestNonRTThread;
00046     m_hostDescriptor.midi_send = DSSIPluginInstance::midiSend;
00047 }
00048 
00049 DSSIPluginFactory::~DSSIPluginFactory()
00050 {
00051     // nothing else to do here either
00052 }
00053 
00054 void
00055 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list)
00056 {
00057     for (std::vector<QString>::iterator i = m_identifiers.begin();
00058          i != m_identifiers.end(); ++i) {
00059 
00060         const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i);
00061         if (!ddesc) continue;
00062 
00063         const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin;
00064         if (!descriptor) continue;
00065         
00066 //      std::cerr << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << std::endl;
00067 
00068         list.push_back(*i);
00069         list.push_back(descriptor->Name);
00070         list.push_back(QString("%1").arg(descriptor->UniqueID));
00071         list.push_back(descriptor->Label);
00072         list.push_back(descriptor->Maker);
00073         list.push_back(descriptor->Copyright);
00074         list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false");
00075         list.push_back(ddesc->run_multiple_synths ? "true" : "false");
00076         list.push_back(m_taxonomy[*i]);
00077         list.push_back(QString("%1").arg(descriptor->PortCount));
00078 
00079         for (unsigned long p = 0; p < descriptor->PortCount; ++p) {
00080 
00081             int type = 0;
00082             if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
00083                 type |= PortType::Control;
00084             } else {
00085                 type |= PortType::Audio;
00086             }
00087             if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
00088                 type |= PortType::Input;
00089             } else {
00090                 type |= PortType::Output;
00091             }
00092 
00093             list.push_back(QString("%1").arg(p));
00094             list.push_back(descriptor->PortNames[p]);
00095             list.push_back(QString("%1").arg(type));
00096             list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
00097             list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
00098             list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
00099             list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
00100         }
00101     }
00102 
00103     unloadUnusedLibraries();
00104 }
00105         
00106 RealTimePluginInstance *
00107 DSSIPluginFactory::instantiatePlugin(QString identifier,
00108                                      int instrument,
00109                                      int position,
00110                                      unsigned int sampleRate,
00111                                      unsigned int blockSize,
00112                                      unsigned int channels)
00113 {
00114     const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier);
00115 
00116     if (descriptor) {
00117 
00118         DSSIPluginInstance *instance =
00119             new DSSIPluginInstance
00120             (this, instrument, identifier, position, sampleRate, blockSize, channels,
00121              descriptor);
00122 
00123         m_instances.insert(instance);
00124 
00125         return instance;
00126     }
00127 
00128     return 0;
00129 }
00130 
00131 const DSSI_Descriptor *
00132 DSSIPluginFactory::getDSSIDescriptor(QString identifier)
00133 {
00134     QString type, soname, label;
00135     PluginIdentifier::parseIdentifier(identifier, type, soname, label);
00136 
00137     if (soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
00138         if (label == "sample_player") {
00139             const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0);
00140             if (descriptor) {
00141                 descriptor->receive_host_descriptor(&m_hostDescriptor);
00142             }
00143             return descriptor;
00144         } else {
00145             return 0;
00146         }
00147     }
00148     
00149     bool firstInLibrary = false;
00150 
00151     if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
00152         loadLibrary(soname);
00153         if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
00154             std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname.toStdString() << std::endl;
00155             return 0;
00156         }
00157         firstInLibrary = true;
00158     }
00159 
00160     void *libraryHandle = m_libraryHandles[soname];
00161 
00162     DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
00163         DLSYM(libraryHandle, "dssi_descriptor");
00164 
00165     if (!fn) {
00166         std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname.toStdString() << std::endl;
00167         return 0;
00168     }
00169 
00170     const DSSI_Descriptor *descriptor = 0;
00171     
00172     int index = 0;
00173     while ((descriptor = fn(index))) {
00174         if (descriptor->LADSPA_Plugin->Label == label) {
00175             if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) {
00176                 descriptor->receive_host_descriptor(&m_hostDescriptor);
00177             }
00178             return descriptor;
00179         }
00180         ++index;
00181     }
00182 
00183     std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label.toStdString() << " in library " << soname.toStdString() << std::endl;
00184 
00185     return 0;
00186 }
00187 
00188 const LADSPA_Descriptor *
00189 DSSIPluginFactory::getLADSPADescriptor(QString identifier)
00190 {
00191     const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier);
00192     if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin;
00193     else return 0;
00194 }
00195 
00196 
00197 std::vector<QString>
00198 DSSIPluginFactory::getPluginPath()
00199 {
00200     std::vector<QString> pathList;
00201     std::string path;
00202 
00203     char *cpath = getenv("DSSI_PATH");
00204     if (cpath) path = cpath;
00205 
00206     if (path == "") {
00207 
00208         path = DEFAULT_DSSI_PATH;
00209 
00210         char *home = getenv("HOME");
00211         if (home) {
00212             std::string::size_type f;
00213             while ((f = path.find("$HOME")) != std::string::npos &&
00214                    f < path.length()) {
00215                 path.replace(f, 5, home);
00216             }
00217         }
00218 
00219 #ifdef _WIN32
00220         char *pfiles = getenv("ProgramFiles");
00221         if (!pfiles) pfiles = "C:\\Program Files";
00222         {
00223         std::string::size_type f;
00224         while ((f = path.find("%ProgramFiles%")) != std::string::npos &&
00225                f < path.length()) {
00226             path.replace(f, 14, pfiles);
00227         }
00228         }
00229 #endif
00230     }
00231 
00232     std::string::size_type index = 0, newindex = 0;
00233 
00234     while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
00235         pathList.push_back(path.substr(index, newindex - index).c_str());
00236         index = newindex + 1;
00237     }
00238     
00239     pathList.push_back(path.substr(index).c_str());
00240 
00241     return pathList;
00242 }
00243 
00244 
00245 std::vector<QString>
00246 DSSIPluginFactory::getLRDFPath(QString &baseUri)
00247 {
00248     std::vector<QString> lrdfPaths;
00249 
00250 #ifdef HAVE_LRDF
00251     std::vector<QString> pathList = getPluginPath();
00252 
00253     lrdfPaths.push_back("/usr/local/share/dssi/rdf");
00254     lrdfPaths.push_back("/usr/share/dssi/rdf");
00255 
00256     lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
00257     lrdfPaths.push_back("/usr/share/ladspa/rdf");
00258 
00259     for (std::vector<QString>::iterator i = pathList.begin();
00260          i != pathList.end(); ++i) {
00261         lrdfPaths.push_back(*i + "/rdf");
00262     }
00263 
00264 #ifdef DSSI_BASE
00265     baseUri = DSSI_BASE;
00266 #else
00267     baseUri = "http://dssi.sourceforge.net/ontology#";
00268 #endif
00269 #endif
00270 
00271     return lrdfPaths;
00272 }    
00273 
00274 
00275 void
00276 DSSIPluginFactory::discoverPlugins(QString soname)
00277 {
00278     // Note that soname is expected to be a full path at this point,
00279     // of a file that is known to exist
00280 
00281     void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
00282 
00283     if (!libraryHandle) {
00284         std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
00285                   << soname.toStdString() << " - " << DLERROR() << std::endl;
00286         return;
00287     }
00288 
00289     DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
00290         DLSYM(libraryHandle, "dssi_descriptor");
00291 
00292     if (!fn) {
00293         std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname.toStdString() << std::endl;
00294         return;
00295     }
00296 
00297     const DSSI_Descriptor *descriptor = 0;
00298     
00299     int index = 0;
00300     while ((descriptor = fn(index))) {
00301 
00302         const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
00303         if (!ladspaDescriptor) {
00304             std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname.toStdString() << std::endl;
00305             ++index;
00306             continue;
00307         }
00308 
00309         RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor;
00310         rtd->name = ladspaDescriptor->Name;
00311         rtd->label = ladspaDescriptor->Label;
00312         rtd->maker = ladspaDescriptor->Maker;
00313         rtd->copyright = ladspaDescriptor->Copyright;
00314         rtd->category = "";
00315         rtd->isSynth = (descriptor->run_synth ||
00316                         descriptor->run_multiple_synths);
00317         rtd->parameterCount = 0;
00318         rtd->audioInputPortCount = 0;
00319         rtd->audioOutputPortCount = 0;
00320         rtd->controlOutputPortCount = 0;
00321 
00322         QString identifier = PluginIdentifier::createIdentifier
00323             ("dssi", soname, ladspaDescriptor->Label);
00324 
00325 #ifdef HAVE_LRDF
00326         char *def_uri = 0;
00327         lrdf_defaults *defs = 0;
00328                 
00329         QString category = m_taxonomy[identifier];
00330 
00331         if (category == "" && m_lrdfTaxonomy[ladspaDescriptor->UniqueID] != "") {
00332             m_taxonomy[identifier] = m_lrdfTaxonomy[ladspaDescriptor->UniqueID];
00333             category = m_taxonomy[identifier];
00334         }
00335 
00336         if (category == "" && ladspaDescriptor->Name != 0) {
00337             std::string name = ladspaDescriptor->Name;
00338             if (name.length() > 4 &&
00339                 name.substr(name.length() - 4) == " VST") {
00340                 if (descriptor->run_synth || descriptor->run_multiple_synths) {
00341                     category = "VST instruments";
00342                 } else {
00343                     category = "VST effects";
00344                 }
00345                 m_taxonomy[identifier] = category;
00346             }
00347         }
00348 
00349         rtd->category = category.toStdString();
00350         
00351 //      std::cerr << "Plugin id is " << ladspaDescriptor->UniqueID
00352 //                  << ", identifier is \"" << identifier.toStdString()
00353 //                << "\", category is \"" << category.toStdString()
00354 //                << "\", name is " << ladspaDescriptor->Name
00355 //                << ", label is " << ladspaDescriptor->Label
00356 //                << std::endl;
00357         
00358         def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
00359         if (def_uri) {
00360             defs = lrdf_get_setting_values(def_uri);
00361         }
00362         
00363         unsigned int controlPortNumber = 1;
00364         
00365         for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
00366             
00367             if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
00368                 
00369                 if (def_uri && defs) {
00370                     
00371                     for (unsigned int j = 0; j < defs->count; j++) {
00372                         if (defs->items[j].pid == controlPortNumber) {
00373 //                          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 " << ladspaDescriptor->PortNames[i] << std::endl;
00374                             m_portDefaults[ladspaDescriptor->UniqueID][i] =
00375                                 defs->items[j].value;
00376                         }
00377                     }
00378                 }
00379                 
00380                 ++controlPortNumber;
00381             }
00382         }
00383 #endif // HAVE_LRDF
00384 
00385         for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
00386             if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
00387                 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
00388                     ++rtd->parameterCount;
00389                 } else {
00390                     if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
00391                         strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
00392                         ++rtd->controlOutputPortCount;
00393                         rtd->controlOutputPortNames.push_back
00394                             (ladspaDescriptor->PortNames[i]);
00395                     }
00396                 }
00397             } else {
00398                 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
00399                     ++rtd->audioInputPortCount;
00400                 } else if (LADSPA_IS_PORT_OUTPUT(ladspaDescriptor->PortDescriptors[i])) {
00401                     ++rtd->audioOutputPortCount;
00402                 }
00403             }
00404         }
00405 
00406         m_identifiers.push_back(identifier);
00407 
00408         m_rtDescriptors[identifier] = rtd;
00409 
00410         ++index;
00411     }
00412 
00413     if (DLCLOSE(libraryHandle) != 0) {
00414         std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << std::endl;
00415         return;
00416     }
00417 }
00418 
00419     
00420 

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