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