svcore  1.9
DSSIPluginFactory.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.
19 */
20 
21 #include "DSSIPluginFactory.h"
22 #include <iostream>
23 
24 #include <QString>
25 
26 #include "DSSIPluginInstance.h"
27 #include "PluginIdentifier.h"
28 
29 #include <cstdlib>
30 
31 #include "base/Profiler.h"
32 
35 
36 #include "system/System.h"
37 
38 #ifdef HAVE_LRDF
39 #include "lrdf.h"
40 #endif // HAVE_LRDF
41 
42 
45 {
46  m_hostDescriptor.DSSI_API_Version = 2;
47  m_hostDescriptor.request_transport_information = NULL;
51 }
52 
54 {
55  // nothing else to do here either
56 }
57 
58 void
59 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list)
60 {
61  Profiler profiler("DSSIPluginFactory::enumeratePlugins");
62 
63  for (std::vector<QString>::iterator i = m_identifiers.begin();
64  i != m_identifiers.end(); ++i) {
65 
66  const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i);
67  if (!ddesc) continue;
68 
69  const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin;
70  if (!descriptor) continue;
71 
72 // SVDEBUG << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << endl;
73 
74  list.push_back(*i);
75  list.push_back(descriptor->Name);
76  list.push_back(QString("%1").arg(descriptor->UniqueID));
77  list.push_back(descriptor->Label);
78  list.push_back(descriptor->Maker);
79  list.push_back(descriptor->Copyright);
80  list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false");
81  list.push_back(ddesc->run_multiple_synths ? "true" : "false");
82  list.push_back(m_taxonomy[*i]);
83  list.push_back(QString("%1").arg(descriptor->PortCount));
84 
85  for (unsigned long p = 0; p < descriptor->PortCount; ++p) {
86 
87  int type = 0;
88  if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
89  type |= PortType::Control;
90  } else {
91  type |= PortType::Audio;
92  }
93  if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
94  type |= PortType::Input;
95  } else {
96  type |= PortType::Output;
97  }
98 
99  list.push_back(QString("%1").arg(p));
100  list.push_back(descriptor->PortNames[p]);
101  list.push_back(QString("%1").arg(type));
102  list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
103  list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
104  list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
105  list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
106  }
107  }
108 
110 }
111 
114  int instrument,
115  int position,
116  unsigned int sampleRate,
117  unsigned int blockSize,
118  unsigned int channels)
119 {
120  Profiler profiler("DSSIPluginFactory::instantiatePlugin");
121 
122  const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier);
123 
124  if (descriptor) {
125 
128  (this, instrument, identifier, position, sampleRate, blockSize, channels,
129  descriptor);
130 
131  m_instances.insert(instance);
132 
133  return instance;
134  }
135 
136  return 0;
137 }
138 
139 const DSSI_Descriptor *
141 {
142  QString type, soname, label;
143  PluginIdentifier::parseIdentifier(identifier, type, soname, label);
144 
146  if (label == "sample_player") {
147  const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0);
148  if (descriptor) {
149  descriptor->receive_host_descriptor(&m_hostDescriptor);
150  }
151  return descriptor;
152  } else {
153  return 0;
154  }
155  }
156 
157  bool firstInLibrary = false;
158 
159  if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
160  loadLibrary(soname);
161  if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
162  cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname << endl;
163  return 0;
164  }
165  firstInLibrary = true;
166  }
167 
168  void *libraryHandle = m_libraryHandles[soname];
169 
170  DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
171  DLSYM(libraryHandle, "dssi_descriptor");
172 
173  if (!fn) {
174  cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname << endl;
175  return 0;
176  }
177 
178  const DSSI_Descriptor *descriptor = 0;
179 
180  int index = 0;
181  while ((descriptor = fn(index))) {
182  if (descriptor->LADSPA_Plugin->Label == label) {
183  if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) {
184  descriptor->receive_host_descriptor(&m_hostDescriptor);
185  }
186  return descriptor;
187  }
188  ++index;
189  }
190 
191  cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label << " in library " << soname << endl;
192 
193  return 0;
194 }
195 
196 const LADSPA_Descriptor *
198 {
199  const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier);
200  if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin;
201  else return 0;
202 }
203 
204 
205 std::vector<QString>
207 {
208  std::vector<QString> pathList;
209  std::string path;
210 
211  char *cpath = getenv("DSSI_PATH");
212  if (cpath) path = cpath;
213 
214  if (path == "") {
215 
216  path = DEFAULT_DSSI_PATH;
217 
218  char *home = getenv("HOME");
219  if (home) {
220  std::string::size_type f;
221  while ((f = path.find("$HOME")) != std::string::npos &&
222  f < path.length()) {
223  path.replace(f, 5, home);
224  }
225  }
226 
227 #ifdef _WIN32
228  char *pfiles = getenv("ProgramFiles");
229  if (!pfiles) pfiles = "C:\\Program Files";
230  {
231  std::string::size_type f;
232  while ((f = path.find("%ProgramFiles%")) != std::string::npos &&
233  f < path.length()) {
234  path.replace(f, 14, pfiles);
235  }
236  }
237 #endif
238  }
239 
240  std::string::size_type index = 0, newindex = 0;
241 
242  while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
243  pathList.push_back(path.substr(index, newindex - index).c_str());
244  index = newindex + 1;
245  }
246 
247  pathList.push_back(path.substr(index).c_str());
248 
249  return pathList;
250 }
251 
252 
253 std::vector<QString>
255 {
256  std::vector<QString> lrdfPaths;
257 
258 #ifdef HAVE_LRDF
259  std::vector<QString> pathList = getPluginPath();
260 
261  lrdfPaths.push_back("/usr/local/share/dssi/rdf");
262  lrdfPaths.push_back("/usr/share/dssi/rdf");
263 
264  lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
265  lrdfPaths.push_back("/usr/share/ladspa/rdf");
266 
267  for (std::vector<QString>::iterator i = pathList.begin();
268  i != pathList.end(); ++i) {
269  lrdfPaths.push_back(*i + "/rdf");
270  }
271 
272 #ifdef DSSI_BASE
273  baseUri = DSSI_BASE;
274 #else
275  baseUri = "http://dssi.sourceforge.net/ontology#";
276 #endif
277 #else
278  // avoid unused parameter
279  baseUri = "";
280 #endif
281 
282  return lrdfPaths;
283 }
284 
285 
286 void
288 {
289  Profiler profiler("DSSIPluginFactory::discoverPlugins");
290 
291  // Note that soname is expected to be a full path at this point,
292  // of a file that is known to exist
293 
294  void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
295 
296  if (!libraryHandle) {
297  cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
298  << soname << " - " << DLERROR() << endl;
299  return;
300  }
301 
302  DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
303  DLSYM(libraryHandle, "dssi_descriptor");
304 
305  if (!fn) {
306  cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname << endl;
307  return;
308  }
309 
310  const DSSI_Descriptor *descriptor = 0;
311 
312  int index = 0;
313  while ((descriptor = fn(index))) {
314 
315  const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
316  if (!ladspaDescriptor) {
317  cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname << endl;
318  ++index;
319  continue;
320  }
321 
323  rtd->name = ladspaDescriptor->Name;
324  rtd->label = ladspaDescriptor->Label;
325  rtd->maker = ladspaDescriptor->Maker;
326  rtd->copyright = ladspaDescriptor->Copyright;
327  rtd->category = "";
328  rtd->isSynth = (descriptor->run_synth ||
329  descriptor->run_multiple_synths);
330  rtd->parameterCount = 0;
331  rtd->audioInputPortCount = 0;
332  rtd->audioOutputPortCount = 0;
333  rtd->controlOutputPortCount = 0;
334 
335  QString identifier = PluginIdentifier::createIdentifier
336  ("dssi", soname, ladspaDescriptor->Label);
337 
338 #ifdef HAVE_LRDF
339  char *def_uri = 0;
340  lrdf_defaults *defs = 0;
341 
342  QString category = m_taxonomy[identifier];
343 
344  if (category == "" && m_lrdfTaxonomy[ladspaDescriptor->UniqueID] != "") {
345  m_taxonomy[identifier] = m_lrdfTaxonomy[ladspaDescriptor->UniqueID];
346  category = m_taxonomy[identifier];
347  }
348 
349  if (category == "") {
350  std::string name = rtd->name;
351  if (name.length() > 4 &&
352  name.substr(name.length() - 4) == " VST") {
353  if (descriptor->run_synth || descriptor->run_multiple_synths) {
354  category = "VST instruments";
355  } else {
356  category = "VST effects";
357  }
358  m_taxonomy[identifier] = category;
359  }
360  }
361 
362  rtd->category = category.toStdString();
363 
364 // cerr << "Plugin id is " << ladspaDescriptor->UniqueID
365 // << ", identifier is \"" << identifier
366 // << "\", category is \"" << category
367 // << "\", name is " << ladspaDescriptor->Name
368 // << ", label is " << ladspaDescriptor->Label
369 // << endl;
370 
371  def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
372  if (def_uri) {
373  defs = lrdf_get_setting_values(def_uri);
374  }
375 
376  unsigned int controlPortNumber = 1;
377 
378  for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
379 
380  if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
381 
382  if (def_uri && defs) {
383 
384  for (unsigned int j = 0; j < defs->count; j++) {
385  if (defs->items[j].pid == controlPortNumber) {
386 // 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;
387  m_portDefaults[ladspaDescriptor->UniqueID][i] =
388  defs->items[j].value;
389  }
390  }
391  }
392 
393  ++controlPortNumber;
394  }
395  }
396 #endif // HAVE_LRDF
397 
398  for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
399  if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
400  if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
401  ++rtd->parameterCount;
402  } else {
403  if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
404  strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
405  ++rtd->controlOutputPortCount;
406  rtd->controlOutputPortNames.push_back
407  (ladspaDescriptor->PortNames[i]);
408  }
409  }
410  } else {
411  if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
412  ++rtd->audioInputPortCount;
413  } else if (LADSPA_IS_PORT_OUTPUT(ladspaDescriptor->PortDescriptors[i])) {
414  ++rtd->audioOutputPortCount;
415  }
416  }
417  }
418 
419  m_identifiers.push_back(identifier);
420 
421  m_rtDescriptors[identifier] = rtd;
422 
423  ++index;
424  }
425 
426  if (DLCLOSE(libraryHandle) != 0) {
427  cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << endl;
428  return;
429  }
430 }
431 
432 
433 
std::vector< std::string > controlOutputPortNames
#define DLERROR()
Definition: System.h:89
#define DLOPEN(a, b)
Definition: System.h:86
static int requestMidiSend(LADSPA_Handle instance, unsigned char ports, unsigned char channels)
int getPortDisplayHint(const LADSPA_Descriptor *, int port)
static const int Input
static void midiSend(LADSPA_Handle instance, snd_seq_event_t *events, unsigned long eventCount)
LibraryHandleMap m_libraryHandles
virtual const LADSPA_Descriptor * getLADSPADescriptor(QString identifier)
virtual void enumeratePlugins(std::vector< QString > &list)
Append to the given list descriptions of all the available plugins and their ports.
static void parseIdentifier(QString identifier, QString &type, QString &soName, QString &label)
static QString createIdentifier(QString type, QString soName, QString label)
virtual std::vector< QString > getPluginPath()
float getPortDefault(const LADSPA_Descriptor *, int port)
virtual RealTimePluginInstance * instantiatePlugin(QString identifier, int clientId, int position, unsigned int sampleRate, unsigned int blockSize, unsigned int channels)
Instantiate a plugin.
static const DSSI_Descriptor * getDescriptor(unsigned long index)
float getPortMaximum(const LADSPA_Descriptor *, int port)
static QString BUILTIN_PLUGIN_SONAME
virtual const DSSI_Descriptor * getDSSIDescriptor(QString identifier)
DSSI_Host_Descriptor m_hostDescriptor
static const int Audio
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 int requestNonRTThread(LADSPA_Handle instance, void(*runFunction)(LADSPA_Handle))
std::vector< QString > m_identifiers
virtual std::vector< QString > getLRDFPath(QString &baseUri)
std::map< unsigned long, QString > m_lrdfTaxonomy
static RealTimePluginFactory * instance(QString pluginType)
#define DEFAULT_DSSI_PATH
Definition: System.h:127
void loadLibrary(QString soName)
static const int Control
virtual void discoverPluginsFrom(QString soName)
float getPortMinimum(const LADSPA_Descriptor *, int port)
static const int Output
#define DLSYM(a, b)
Definition: System.h:87
Profile point instance class.
Definition: Profiler.h:86