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