svcore  1.9
LADSPAPluginFactory.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 /*
16  This is a modified version of a source file from the
17  Rosegarden MIDI and audio sequencer and notation editor.
18  This file copyright 2000-2006 Chris Cannam and Richard Bown.
19 */
20 
21 #include "LADSPAPluginFactory.h"
22 #include <iostream>
23 
24 #include <QDir>
25 #include <QFile>
26 #include <QTextStream>
27 
28 #include <cmath>
29 
30 #include "LADSPAPluginInstance.h"
31 #include "PluginIdentifier.h"
32 
33 #include "system/System.h"
34 #include "base/Preferences.h"
35 #include "base/Profiler.h"
36 
37 //#define DEBUG_LADSPA_PLUGIN_FACTORY 1
38 
39 #ifdef HAVE_LRDF
40 #include "lrdf.h"
41 #endif // HAVE_LRDF
42 
43 
45 {
46 #ifdef HAVE_LRDF
47  lrdf_init();
48 #endif
49 }
50 
52 {
53  for (std::set<RealTimePluginInstance *>::iterator i = m_instances.begin();
54  i != m_instances.end(); ++i) {
55  (*i)->setFactory(0);
56  delete *i;
57  }
58  m_instances.clear();
60 
61 #ifdef HAVE_LRDF
62  lrdf_cleanup();
63 #endif // HAVE_LRDF
64 }
65 
66 const std::vector<QString> &
68 {
69  return m_identifiers;
70 }
71 
72 void
73 LADSPAPluginFactory::enumeratePlugins(std::vector<QString> &list)
74 {
75  Profiler profiler("LADSPAPluginFactory::enumeratePlugins");
76 
77  for (std::vector<QString>::iterator i = m_identifiers.begin();
78  i != m_identifiers.end(); ++i) {
79 
80  const LADSPA_Descriptor *descriptor = getLADSPADescriptor(*i);
81 
82  if (!descriptor) {
83  cerr << "WARNING: LADSPAPluginFactory::enumeratePlugins: couldn't get descriptor for identifier " << *i << endl;
84  continue;
85  }
86 
87  list.push_back(*i);
88  list.push_back(descriptor->Name);
89  list.push_back(QString("%1").arg(descriptor->UniqueID));
90  list.push_back(descriptor->Label);
91  list.push_back(descriptor->Maker);
92  list.push_back(descriptor->Copyright);
93  list.push_back("false"); // is synth
94  list.push_back("false"); // is grouped
95 
96  if (m_taxonomy.find(*i) != m_taxonomy.end() && m_taxonomy[*i] != "") {
97 // cerr << "LADSPAPluginFactory: cat for " << *i << " found in taxonomy as " << m_taxonomy[descriptor->UniqueID] << endl;
98  list.push_back(m_taxonomy[*i]);
99  } else {
100  list.push_back("");
101 // cerr << "LADSPAPluginFactory: cat for " << *i << " not found (despite having " << m_fallbackCategories.size() << " fallbacks)" << endl;
102 
103  }
104 
105  list.push_back(QString("%1").arg(descriptor->PortCount));
106 
107  for (unsigned long p = 0; p < descriptor->PortCount; ++p) {
108 
109  int type = 0;
110  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
111  type |= PortType::Control;
112  } else {
113  type |= PortType::Audio;
114  }
115  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
116  type |= PortType::Input;
117  } else {
118  type |= PortType::Output;
119  }
120 
121  list.push_back(QString("%1").arg(p));
122  list.push_back(descriptor->PortNames[p]);
123  list.push_back(QString("%1").arg(type));
124  list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
125  list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
126  list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
127  list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
128  }
129  }
130 
132 }
133 
136 {
137  std::map<QString, RealTimePluginDescriptor *>::const_iterator i =
138  m_rtDescriptors.find(identifier);
139 
140  if (i != m_rtDescriptors.end()) {
141  return i->second;
142  }
143 
144  return 0;
145 }
146 
147 float
148 LADSPAPluginFactory::getPortMinimum(const LADSPA_Descriptor *descriptor, int port)
149 {
150  LADSPA_PortRangeHintDescriptor d =
151  descriptor->PortRangeHints[port].HintDescriptor;
152 
153  float minimum = 0.0;
154 
155  if (LADSPA_IS_HINT_BOUNDED_BELOW(d)) {
156  float lb = descriptor->PortRangeHints[port].LowerBound;
157  minimum = lb;
158  } else if (LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
159  float ub = descriptor->PortRangeHints[port].UpperBound;
160  minimum = std::min(0.0, ub - 1.0);
161  }
162 
163  if (LADSPA_IS_HINT_SAMPLE_RATE(d)) {
164  minimum *= m_sampleRate;
165  }
166 
167  if (LADSPA_IS_HINT_LOGARITHMIC(d)) {
168  if (minimum == 0.f) minimum = 1.f;
169  }
170 
171  return minimum;
172 }
173 
174 float
175 LADSPAPluginFactory::getPortMaximum(const LADSPA_Descriptor *descriptor, int port)
176 {
177  LADSPA_PortRangeHintDescriptor d =
178  descriptor->PortRangeHints[port].HintDescriptor;
179 
180  float maximum = 1.0;
181 
182  if (LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
183  float ub = descriptor->PortRangeHints[port].UpperBound;
184  maximum = ub;
185  } else {
186  float lb = descriptor->PortRangeHints[port].LowerBound;
187  maximum = lb + 1.0;
188  }
189 
190  if (LADSPA_IS_HINT_SAMPLE_RATE(d)) {
191  maximum *= m_sampleRate;
192  }
193 
194  return maximum;
195 }
196 
197 float
198 LADSPAPluginFactory::getPortDefault(const LADSPA_Descriptor *descriptor, int port)
199 {
200  float minimum = getPortMinimum(descriptor, port);
201  float maximum = getPortMaximum(descriptor, port);
202  float deft;
203 
204  if (m_portDefaults.find(descriptor->UniqueID) !=
205  m_portDefaults.end()) {
206  if (m_portDefaults[descriptor->UniqueID].find(port) !=
207  m_portDefaults[descriptor->UniqueID].end()) {
208 
209  deft = m_portDefaults[descriptor->UniqueID][port];
210  if (deft < minimum) deft = minimum;
211  if (deft > maximum) deft = maximum;
212  return deft;
213  }
214  }
215 
216  LADSPA_PortRangeHintDescriptor d =
217  descriptor->PortRangeHints[port].HintDescriptor;
218 
219  bool logarithmic = LADSPA_IS_HINT_LOGARITHMIC(d);
220 
221  float logmin = 0, logmax = 0;
222  if (logarithmic) {
223  float thresh = powf(10, -10);
224  if (minimum < thresh) logmin = -10;
225  else logmin = log10f(minimum);
226  if (maximum < thresh) logmax = -10;
227  else logmax = log10f(maximum);
228  }
229 
230 // SVDEBUG << "LADSPAPluginFactory::getPortDefault: hint = " << d << endl;
231 
232  if (!LADSPA_IS_HINT_HAS_DEFAULT(d)) {
233 
234  deft = minimum;
235 
236  } else if (LADSPA_IS_HINT_DEFAULT_MINIMUM(d)) {
237 
238  deft = minimum;
239 
240  } else if (LADSPA_IS_HINT_DEFAULT_LOW(d)) {
241 
242  if (logarithmic) {
243  deft = powf(10, logmin * 0.75 + logmax * 0.25);
244  } else {
245  deft = minimum * 0.75 + maximum * 0.25;
246  }
247 
248  } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(d)) {
249 
250  if (logarithmic) {
251  deft = powf(10, logmin * 0.5 + logmax * 0.5);
252  } else {
253  deft = minimum * 0.5 + maximum * 0.5;
254  }
255 
256  } else if (LADSPA_IS_HINT_DEFAULT_HIGH(d)) {
257 
258  if (logarithmic) {
259  deft = powf(10, logmin * 0.25 + logmax * 0.75);
260  } else {
261  deft = minimum * 0.25 + maximum * 0.75;
262  }
263 
264  } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(d)) {
265 
266  deft = maximum;
267 
268  } else if (LADSPA_IS_HINT_DEFAULT_0(d)) {
269 
270  deft = 0.0;
271 
272  } else if (LADSPA_IS_HINT_DEFAULT_1(d)) {
273 
274  deft = 1.0;
275 
276  } else if (LADSPA_IS_HINT_DEFAULT_100(d)) {
277 
278  deft = 100.0;
279 
280  } else if (LADSPA_IS_HINT_DEFAULT_440(d)) {
281 
282 // deft = 440.0;
284 
285  } else {
286 
287  deft = minimum;
288  }
289 
291 //so it would happen twice if we did it here -- and e.g. DEFAULT_440
292 //doesn't want to be multiplied by the rate either
293 
294 // if (LADSPA_IS_HINT_SAMPLE_RATE(d)) {
295 // deft *= m_sampleRate;
296 // }
297 
298  return deft;
299 }
300 
301 float
302 LADSPAPluginFactory::getPortQuantization(const LADSPA_Descriptor *descriptor, int port)
303 {
304  int displayHint = getPortDisplayHint(descriptor, port);
305  if (displayHint & PortHint::Toggled) {
306  return lrintf(getPortMaximum(descriptor, port)) -
307  lrintf(getPortMinimum(descriptor, port));
308  }
309  if (displayHint & PortHint::Integer) {
310  return 1.0;
311  }
312  return 0.0;
313 }
314 
315 int
316 LADSPAPluginFactory::getPortDisplayHint(const LADSPA_Descriptor *descriptor, int port)
317 {
318  LADSPA_PortRangeHintDescriptor d =
319  descriptor->PortRangeHints[port].HintDescriptor;
320  int hint = PortHint::NoHint;
321 
322  if (LADSPA_IS_HINT_TOGGLED(d)) hint |= PortHint::Toggled;
323  if (LADSPA_IS_HINT_INTEGER(d)) hint |= PortHint::Integer;
324  if (LADSPA_IS_HINT_LOGARITHMIC(d)) hint |= PortHint::Logarithmic;
325 
326  return hint;
327 }
328 
329 
332  int instrument,
333  int position,
334  unsigned int sampleRate,
335  unsigned int blockSize,
336  unsigned int channels)
337 {
338  Profiler profiler("LADSPAPluginFactory::instantiatePlugin");
339 
340  const LADSPA_Descriptor *descriptor = getLADSPADescriptor(identifier);
341 
342  if (descriptor) {
343 
346  (this, instrument, identifier, position, sampleRate, blockSize, channels,
347  descriptor);
348 
349  m_instances.insert(instance);
350 
351 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
352  SVDEBUG << "LADSPAPluginFactory::instantiatePlugin("
353  << identifier << ": now have " << m_instances.size() << " instances" << endl;
354 #endif
355 
356  return instance;
357  }
358 
359  return 0;
360 }
361 
362 void
364  QString identifier)
365 {
366  Profiler profiler("LADSPAPluginFactory::releasePlugin");
367 
368  if (m_instances.find(instance) == m_instances.end()) {
369  cerr << "WARNING: LADSPAPluginFactory::releasePlugin: Not one of mine!"
370  << endl;
371  return;
372  }
373 
374  QString type, soname, label;
375  PluginIdentifier::parseIdentifier(identifier, type, soname, label);
376 
377  m_instances.erase(instance);
378 
379  bool stillInUse = false;
380 
381  for (std::set<RealTimePluginInstance *>::iterator ii = m_instances.begin();
382  ii != m_instances.end(); ++ii) {
383  QString itype, isoname, ilabel;
384  PluginIdentifier::parseIdentifier((*ii)->getPluginIdentifier(), itype, isoname, ilabel);
385  if (isoname == soname) {
386 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
387  SVDEBUG << "LADSPAPluginFactory::releasePlugin: dll " << soname << " is still in use for plugin " << ilabel << endl;
388 #endif
389  stillInUse = true;
390  break;
391  }
392  }
393 
394  if (!stillInUse) {
396 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
397  SVDEBUG << "LADSPAPluginFactory::releasePlugin: dll " << soname << " no longer in use, unloading" << endl;
398 #endif
399  unloadLibrary(soname);
400  }
401  }
402 
403 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
404  SVDEBUG << "LADSPAPluginFactory::releasePlugin("
405  << identifier << ": now have " << m_instances.size() << " instances" << endl;
406 #endif
407 }
408 
409 const LADSPA_Descriptor *
411 {
412  QString type, soname, label;
413  PluginIdentifier::parseIdentifier(identifier, type, soname, label);
414 
415  if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
416  loadLibrary(soname);
417  if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
418  cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: loadLibrary failed for " << soname << endl;
419  return 0;
420  }
421  }
422 
423  void *libraryHandle = m_libraryHandles[soname];
424 
425  LADSPA_Descriptor_Function fn = (LADSPA_Descriptor_Function)
426  DLSYM(libraryHandle, "ladspa_descriptor");
427 
428  if (!fn) {
429  cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: No descriptor function in library " << soname << endl;
430  return 0;
431  }
432 
433  const LADSPA_Descriptor *descriptor = 0;
434 
435  int index = 0;
436  while ((descriptor = fn(index))) {
437  if (descriptor->Label == label) return descriptor;
438  ++index;
439  }
440 
441  cerr << "WARNING: LADSPAPluginFactory::getLADSPADescriptor: No such plugin as " << label << " in library " << soname << endl;
442 
443  return 0;
444 }
445 
446 void
448 {
449  void *libraryHandle = DLOPEN(soName, RTLD_NOW);
450  if (libraryHandle) {
451  m_libraryHandles[soName] = libraryHandle;
452  SVDEBUG << "LADSPAPluginFactory::loadLibrary: Loaded library \"" << soName << "\"" << endl;
453  return;
454  }
455 
456  if (QFileInfo(soName).exists()) {
457  DLERROR();
458  cerr << "LADSPAPluginFactory::loadLibrary: Library \"" << soName << "\" exists, but failed to load it" << endl;
459  return;
460  }
461 
462  std::vector<QString> pathList = getPluginPath();
463 
464  QString fileName = QFile(soName).fileName();
465  QString base = QFileInfo(soName).baseName();
466 
467  for (std::vector<QString>::iterator i = pathList.begin();
468  i != pathList.end(); ++i) {
469 
470 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
471  SVDEBUG << "Looking at: " << (*i) << endl;
472 #endif
473 
474  QDir dir(*i, PLUGIN_GLOB,
475  QDir::Name | QDir::IgnoreCase,
476  QDir::Files | QDir::Readable);
477 
478  if (QFileInfo(dir.filePath(fileName)).exists()) {
479 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
480  cerr << "Loading: " << fileName << endl;
481 #endif
482  libraryHandle = DLOPEN(dir.filePath(fileName), RTLD_NOW);
483  if (libraryHandle) {
484  m_libraryHandles[soName] = libraryHandle;
485  return;
486  }
487  }
488 
489  for (unsigned int j = 0; j < dir.count(); ++j) {
490  QString file = dir.filePath(dir[j]);
491  if (QFileInfo(file).baseName() == base) {
492 #ifdef DEBUG_LADSPA_PLUGIN_FACTORY
493  cerr << "Loading: " << file << endl;
494 #endif
495  libraryHandle = DLOPEN(file, RTLD_NOW);
496  if (libraryHandle) {
497  m_libraryHandles[soName] = libraryHandle;
498  return;
499  }
500  }
501  }
502  }
503 
504  cerr << "LADSPAPluginFactory::loadLibrary: Failed to locate plugin library \"" << soName << "\"" << endl;
505 }
506 
507 void
509 {
510  LibraryHandleMap::iterator li = m_libraryHandles.find(soName);
511  if (li != m_libraryHandles.end()) {
512 // SVDEBUG << "unloading " << soname << endl;
513  DLCLOSE(m_libraryHandles[soName]);
514  m_libraryHandles.erase(li);
515  }
516 }
517 
518 void
520 {
521  std::vector<QString> toUnload;
522 
523  for (LibraryHandleMap::iterator i = m_libraryHandles.begin();
524  i != m_libraryHandles.end(); ++i) {
525 
526  bool stillInUse = false;
527 
528  for (std::set<RealTimePluginInstance *>::iterator ii = m_instances.begin();
529  ii != m_instances.end(); ++ii) {
530 
531  QString itype, isoname, ilabel;
532  PluginIdentifier::parseIdentifier((*ii)->getPluginIdentifier(), itype, isoname, ilabel);
533  if (isoname == i->first) {
534  stillInUse = true;
535  break;
536  }
537  }
538 
539  if (!stillInUse) toUnload.push_back(i->first);
540  }
541 
542  for (std::vector<QString>::iterator i = toUnload.begin();
543  i != toUnload.end(); ++i) {
545  unloadLibrary(*i);
546  }
547  }
548 }
549 
550 
551 // It is only later, after they've gone,
552 // I realize they have delivered a letter.
553 // It's a letter from my wife. "What are you doing
554 // there?" my wife asks. "Are you drinking?"
555 // I study the postmark for hours. Then it, too, begins to fade.
556 // I hope someday to forget all this.
557 
558 
559 std::vector<QString>
561 {
562  std::vector<QString> pathList;
563  std::string path;
564 
565  char *cpath = getenv("LADSPA_PATH");
566  if (cpath) path = cpath;
567 
568  if (path == "") {
569 
570  path = DEFAULT_LADSPA_PATH;
571 
572  char *home = getenv("HOME");
573  if (home) {
574  std::string::size_type f;
575  while ((f = path.find("$HOME")) != std::string::npos &&
576  f < path.length()) {
577  path.replace(f, 5, home);
578  }
579  }
580 
581 #ifdef _WIN32
582  char *pfiles = getenv("ProgramFiles");
583  if (!pfiles) pfiles = "C:\\Program Files";
584  {
585  std::string::size_type f;
586  while ((f = path.find("%ProgramFiles%")) != std::string::npos &&
587  f < path.length()) {
588  path.replace(f, 14, pfiles);
589  }
590  }
591 #endif
592  }
593 
594  std::string::size_type index = 0, newindex = 0;
595 
596  while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
597  pathList.push_back(path.substr(index, newindex - index).c_str());
598  index = newindex + 1;
599  }
600 
601  pathList.push_back(path.substr(index).c_str());
602 
603  return pathList;
604 }
605 
606 
607 std::vector<QString>
609 {
610  std::vector<QString> lrdfPaths;
611 
612 #ifdef HAVE_LRDF
613  std::vector<QString> pathList = getPluginPath();
614 
615  lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
616  lrdfPaths.push_back("/usr/share/ladspa/rdf");
617 
618  for (std::vector<QString>::iterator i = pathList.begin();
619  i != pathList.end(); ++i) {
620  lrdfPaths.push_back(*i + "/rdf");
621  }
622 
623  baseUri = LADSPA_BASE;
624 #else
625  baseUri = "";
626 #endif
627 
628  return lrdfPaths;
629 }
630 
631 void
633 {
634  Profiler profiler("LADSPAPluginFactory::discoverPlugins");
635 
636  std::vector<QString> pathList = getPluginPath();
637 
638 // SVDEBUG << "LADSPAPluginFactory::discoverPlugins - "
639 // << "discovering plugins; path is ";
640 // for (std::vector<QString>::iterator i = pathList.begin();
641 // i != pathList.end(); ++i) {
642 // SVDEBUG << "[" << i-<< "] ";
643 // }
644 // SVDEBUG << endl;
645 
646 #ifdef HAVE_LRDF
647  // read the description files
648  //
649  QString baseUri;
650  std::vector<QString> lrdfPaths = getLRDFPath(baseUri);
651 
652  bool haveSomething = false;
653 
654  for (size_t i = 0; i < lrdfPaths.size(); ++i) {
655  QDir dir(lrdfPaths[i], "*.rdf;*.rdfs");
656  for (unsigned int j = 0; j < dir.count(); ++j) {
657  if (!lrdf_read_file(QString("file:" + lrdfPaths[i] + "/" + dir[j]).toStdString().c_str())) {
658 // cerr << "LADSPAPluginFactory: read RDF file " << (lrdfPaths[i] + "/" + dir[j]) << endl;
659  haveSomething = true;
660  }
661  }
662  }
663 
664  if (haveSomething) {
665  generateTaxonomy(baseUri + "Plugin", "");
666  }
667 #endif // HAVE_LRDF
668 
670 
671  for (std::vector<QString>::iterator i = pathList.begin();
672  i != pathList.end(); ++i) {
673 
674  QDir pluginDir(*i, PLUGIN_GLOB);
675 
676  for (unsigned int j = 0; j < pluginDir.count(); ++j) {
677  discoverPluginsFrom(QString("%1/%2").arg(*i).arg(pluginDir[j]));
678  }
679  }
680 }
681 
682 void
684 {
685  void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
686 
687  if (!libraryHandle) {
688  cerr << "WARNING: LADSPAPluginFactory::discoverPlugins: couldn't load plugin library "
689  << soname << " - " << DLERROR() << endl;
690  return;
691  }
692 
693  LADSPA_Descriptor_Function fn = (LADSPA_Descriptor_Function)
694  DLSYM(libraryHandle, "ladspa_descriptor");
695 
696  if (!fn) {
697  cerr << "WARNING: LADSPAPluginFactory::discoverPlugins: No descriptor function in " << soname << endl;
698  return;
699  }
700 
701  const LADSPA_Descriptor *descriptor = 0;
702 
703  int index = 0;
704  while ((descriptor = fn(index))) {
705 
707  rtd->name = descriptor->Name;
708  rtd->label = descriptor->Label;
709  rtd->maker = descriptor->Maker;
710  rtd->copyright = descriptor->Copyright;
711  rtd->category = "";
712  rtd->isSynth = false;
713  rtd->parameterCount = 0;
714  rtd->audioInputPortCount = 0;
715  rtd->audioOutputPortCount = 0;
716  rtd->controlOutputPortCount = 0;
717 
718  QString identifier = PluginIdentifier::createIdentifier
719  ("ladspa", soname, descriptor->Label);
720 
721 #ifdef HAVE_LRDF
722  char *def_uri = 0;
723  lrdf_defaults *defs = 0;
724 
725  if (m_lrdfTaxonomy[descriptor->UniqueID] != "") {
726  m_taxonomy[identifier] = m_lrdfTaxonomy[descriptor->UniqueID];
727 // cerr << "set id \"" << identifier << "\" to cat \"" << m_taxonomy[identifier] << "\" from LRDF" << endl;
728 // cout << identifier << "::" << m_taxonomy[identifier] << endl;
729  }
730 
731  QString category = m_taxonomy[identifier];
732 
733  if (category == "") {
734  std::string name = rtd->name;
735  if (name.length() > 4 &&
736  name.substr(name.length() - 4) == " VST") {
737  category = "VST effects";
738  m_taxonomy[identifier] = category;
739  }
740  }
741 
742  rtd->category = category.toStdString();
743 
744 // cerr << "Plugin id is " << descriptor->UniqueID
745 // << ", category is \"" << (category ? category : QString("(none)"))
746 // << "\", name is " << descriptor->Name
747 // << ", label is " << descriptor->Label
748 // << endl;
749 
750  def_uri = lrdf_get_default_uri(descriptor->UniqueID);
751  if (def_uri) {
752  defs = lrdf_get_setting_values(def_uri);
753  }
754 
755  unsigned int controlPortNumber = 1;
756 
757  for (unsigned long i = 0; i < descriptor->PortCount; i++) {
758 
759  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) {
760 
761  if (def_uri && defs) {
762 
763  for (unsigned int j = 0; j < defs->count; j++) {
764  if (defs->items[j].pid == controlPortNumber) {
765 // 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;
766  m_portDefaults[descriptor->UniqueID][i] =
767  defs->items[j].value;
768  }
769  }
770  }
771 
772  ++controlPortNumber;
773  }
774  }
775 #endif // HAVE_LRDF
776 
777  for (unsigned long i = 0; i < descriptor->PortCount; i++) {
778  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) {
779  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
780  ++rtd->parameterCount;
781  } else {
782  if (strcmp(descriptor->PortNames[i], "latency") &&
783  strcmp(descriptor->PortNames[i], "_latency")) {
784  ++rtd->controlOutputPortCount;
785  rtd->controlOutputPortNames.push_back
786  (descriptor->PortNames[i]);
787  }
788  }
789  } else {
790  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
791  ++rtd->audioInputPortCount;
792  } else if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[i])) {
793  ++rtd->audioOutputPortCount;
794  }
795  }
796  }
797 
798  m_identifiers.push_back(identifier);
799 
800  m_rtDescriptors[identifier] = rtd;
801 
802  ++index;
803  }
804 
805  if (DLCLOSE(libraryHandle) != 0) {
806  cerr << "WARNING: LADSPAPluginFactory::discoverPlugins - can't unload " << libraryHandle << endl;
807  return;
808  }
809 }
810 
811 void
813 {
814  std::vector<QString> pluginPath = getPluginPath();
815  std::vector<QString> path;
816 
817  for (size_t i = 0; i < pluginPath.size(); ++i) {
818  if (pluginPath[i].contains("/lib/")) {
819  QString p(pluginPath[i]);
820  path.push_back(p);
821  p.replace("/lib/", "/share/");
822  path.push_back(p);
823 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: path element " << p << endl;
824  }
825  path.push_back(pluginPath[i]);
826 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: path element " << pluginPath[i] << endl;
827  }
828 
829  for (size_t i = 0; i < path.size(); ++i) {
830 
831  QDir dir(path[i], "*.cat");
832 
833 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl;
834  for (unsigned int j = 0; j < dir.count(); ++j) {
835 
836  QFile file(path[i] + "/" + dir[j]);
837 
838 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
839 
840  if (file.open(QIODevice::ReadOnly)) {
841 // cerr << "...opened" << endl;
842  QTextStream stream(&file);
843  QString line;
844 
845  while (!stream.atEnd()) {
846  line = stream.readLine();
847 // cerr << "line is: \"" << line << "\"" << endl;
848  QString id = PluginIdentifier::canonicalise
849  (line.section("::", 0, 0));
850  QString cat = line.section("::", 1, 1);
851  m_taxonomy[id] = cat;
852 // cerr << "set id \"" << id << "\" to cat \"" << cat << "\"" << endl;
853  }
854  }
855  }
856  }
857 }
858 
859 void
860 LADSPAPluginFactory::generateTaxonomy(QString uri, QString base)
861 {
862 #ifdef HAVE_LRDF
863  lrdf_uris *uris = lrdf_get_instances(uri.toStdString().c_str());
864 
865  if (uris != NULL) {
866  for (unsigned int i = 0; i < uris->count; ++i) {
867  m_lrdfTaxonomy[lrdf_get_uid(uris->items[i])] = base;
868  }
869  lrdf_free_uris(uris);
870  }
871 
872  uris = lrdf_get_subclasses(uri.toStdString().c_str());
873 
874  if (uris != NULL) {
875  for (unsigned int i = 0; i < uris->count; ++i) {
876  char *label = lrdf_get_label(uris->items[i]);
877  generateTaxonomy(uris->items[i],
878  base + (base.length() > 0 ? " > " : "") + label);
879  }
880  lrdf_free_uris(uris);
881  }
882 #else
883  // avoid unused parameter
884  (void)uri;
885  (void)base;
886 #endif
887 }
888 
889 QString
891 {
892  return m_taxonomy[identifier];
893 }
894 
float getTuningFrequency() const
Definition: Preferences.h:52
std::vector< std::string > controlOutputPortNames
#define DLERROR()
Definition: System.h:89
#define DLOPEN(a, b)
Definition: System.h:86
virtual void discoverPlugins()
Look up the plugin path and find the plugins in it.
void unloadLibrary(QString soName)
int getPortDisplayHint(const LADSPA_Descriptor *, int port)
static QString canonicalise(QString identifier)
static const int Input
static const int NoHint
LibraryHandleMap m_libraryHandles
virtual void generateTaxonomy(QString uri, QString base)
static const int Toggled
static void parseIdentifier(QString identifier, QString &type, QString &soName, QString &label)
static Preferences * getInstance()
Definition: Preferences.cpp:31
static QString createIdentifier(QString type, QString soName, QString label)
float getPortDefault(const LADSPA_Descriptor *, int port)
virtual QString getPluginCategory(QString identifier)
Get category metadata about a plugin (without instantiating it).
virtual std::vector< QString > getPluginPath()
virtual void generateFallbackCategories()
virtual void releasePlugin(RealTimePluginInstance *, QString)
float getPortMaximum(const LADSPA_Descriptor *, int port)
static QString BUILTIN_PLUGIN_SONAME
float getPortQuantization(const LADSPA_Descriptor *, int port)
#define DEFAULT_LADSPA_PATH
Definition: System.h:126
virtual const std::vector< QString > & getPluginIdentifiers() const
Return a reference to a list of all plugin identifiers that can be created by this factory.
static const int Audio
virtual std::vector< QString > getLRDFPath(QString &baseUri)
std::map< unsigned long, std::map< int, float > > m_portDefaults
#define DLCLOSE(a)
Definition: System.h:88
#define PATH_SEPARATOR
Definition: System.h:124
std::set< RealTimePluginInstance * > m_instances
std::map< QString, QString > m_taxonomy
std::map< QString, RealTimePluginDescriptor * > m_rtDescriptors
static const int Logarithmic
#define PLUGIN_GLOB
Definition: System.h:123
std::vector< QString > m_identifiers
#define SVDEBUG
Definition: Debug.h:42
virtual void discoverPluginsFrom(QString soName)
std::map< unsigned long, QString > m_lrdfTaxonomy
virtual RealTimePluginInstance * instantiatePlugin(QString identifier, int clientId, int position, unsigned int sampleRate, unsigned int blockSize, unsigned int channels)
Instantiate a plugin.
static RealTimePluginFactory * instance(QString pluginType)
virtual const RealTimePluginDescriptor * getPluginDescriptor(QString identifier) const
Get some basic information about a plugin (rapidly).
static const int Integer
void loadLibrary(QString soName)
static const int Control
virtual void enumeratePlugins(std::vector< QString > &list)
Append to the given list descriptions of all the available plugins and their ports.
float getPortMinimum(const LADSPA_Descriptor *, int port)
virtual const LADSPA_Descriptor * getLADSPADescriptor(QString identifier)
static const int Output
#define DLSYM(a, b)
Definition: System.h:87
Profile point instance class.
Definition: Profiler.h:86