Mercurial > hg > svcore
comparison plugin/DSSIPluginFactory.cpp @ 0:da6937383da8
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | d86891498eef |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:da6937383da8 |
---|---|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 A waveform viewer and audio annotation editor. | |
5 Chris Cannam, Queen Mary University of London, 2005 | |
6 | |
7 This is experimental software. Not for distribution. | |
8 */ | |
9 | |
10 /* | |
11 This is a modified version of a source file from the | |
12 Rosegarden MIDI and audio sequencer and notation editor. | |
13 This file copyright 2000-2005 Chris Cannam. | |
14 */ | |
15 | |
16 #include "DSSIPluginFactory.h" | |
17 #include <iostream> | |
18 | |
19 #include <QString> | |
20 | |
21 #include "DSSIPluginInstance.h" | |
22 #include "PluginIdentifier.h" | |
23 | |
24 //!!! | |
25 #include "plugins/SamplePlayer.h" | |
26 | |
27 #include "base/System.h" | |
28 | |
29 #ifdef HAVE_LIBLRDF | |
30 #include "lrdf.h" | |
31 #endif // HAVE_LIBLRDF | |
32 | |
33 | |
34 DSSIPluginFactory::DSSIPluginFactory() : | |
35 LADSPAPluginFactory() | |
36 { | |
37 m_hostDescriptor.DSSI_API_Version = 2; | |
38 m_hostDescriptor.request_transport_information = NULL; | |
39 m_hostDescriptor.request_midi_send = DSSIPluginInstance::requestMidiSend; | |
40 m_hostDescriptor.request_non_rt_thread = DSSIPluginInstance::requestNonRTThread; | |
41 m_hostDescriptor.midi_send = DSSIPluginInstance::midiSend; | |
42 } | |
43 | |
44 DSSIPluginFactory::~DSSIPluginFactory() | |
45 { | |
46 // nothing else to do here either | |
47 } | |
48 | |
49 void | |
50 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list) | |
51 { | |
52 for (std::vector<QString>::iterator i = m_identifiers.begin(); | |
53 i != m_identifiers.end(); ++i) { | |
54 | |
55 const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i); | |
56 if (!ddesc) continue; | |
57 | |
58 const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin; | |
59 if (!descriptor) continue; | |
60 | |
61 // std::cerr << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << std::endl; | |
62 | |
63 list.push_back(*i); | |
64 list.push_back(descriptor->Name); | |
65 list.push_back(QString("%1").arg(descriptor->UniqueID)); | |
66 list.push_back(descriptor->Label); | |
67 list.push_back(descriptor->Maker); | |
68 list.push_back(descriptor->Copyright); | |
69 list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false"); | |
70 list.push_back(ddesc->run_multiple_synths ? "true" : "false"); | |
71 list.push_back(m_taxonomy[descriptor->UniqueID]); | |
72 list.push_back(QString("%1").arg(descriptor->PortCount)); | |
73 | |
74 for (unsigned long p = 0; p < descriptor->PortCount; ++p) { | |
75 | |
76 int type = 0; | |
77 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) { | |
78 type |= PortType::Control; | |
79 } else { | |
80 type |= PortType::Audio; | |
81 } | |
82 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) { | |
83 type |= PortType::Input; | |
84 } else { | |
85 type |= PortType::Output; | |
86 } | |
87 | |
88 list.push_back(QString("%1").arg(p)); | |
89 list.push_back(descriptor->PortNames[p]); | |
90 list.push_back(QString("%1").arg(type)); | |
91 list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p))); | |
92 list.push_back(QString("%1").arg(getPortMinimum(descriptor, p))); | |
93 list.push_back(QString("%1").arg(getPortMaximum(descriptor, p))); | |
94 list.push_back(QString("%1").arg(getPortDefault(descriptor, p))); | |
95 } | |
96 } | |
97 | |
98 unloadUnusedLibraries(); | |
99 } | |
100 | |
101 RealTimePluginInstance * | |
102 DSSIPluginFactory::instantiatePlugin(QString identifier, | |
103 int instrument, | |
104 int position, | |
105 unsigned int sampleRate, | |
106 unsigned int blockSize, | |
107 unsigned int channels) | |
108 { | |
109 const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier); | |
110 | |
111 if (descriptor) { | |
112 | |
113 DSSIPluginInstance *instance = | |
114 new DSSIPluginInstance | |
115 (this, instrument, identifier, position, sampleRate, blockSize, channels, | |
116 descriptor); | |
117 | |
118 m_instances.insert(instance); | |
119 | |
120 return instance; | |
121 } | |
122 | |
123 return 0; | |
124 } | |
125 | |
126 const DSSI_Descriptor * | |
127 DSSIPluginFactory::getDSSIDescriptor(QString identifier) | |
128 { | |
129 QString type, soname, label; | |
130 PluginIdentifier::parseIdentifier(identifier, type, soname, label); | |
131 | |
132 if (soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) { | |
133 if (label == "sample_player") { | |
134 const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0); | |
135 if (descriptor) { | |
136 descriptor->receive_host_descriptor(&m_hostDescriptor); | |
137 } | |
138 return descriptor; | |
139 } else { | |
140 return 0; | |
141 } | |
142 } | |
143 | |
144 bool firstInLibrary = false; | |
145 | |
146 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) { | |
147 loadLibrary(soname); | |
148 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) { | |
149 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname.toStdString() << std::endl; | |
150 return 0; | |
151 } | |
152 firstInLibrary = true; | |
153 } | |
154 | |
155 void *libraryHandle = m_libraryHandles[soname]; | |
156 | |
157 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function) | |
158 DLSYM(libraryHandle, "dssi_descriptor"); | |
159 | |
160 if (!fn) { | |
161 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname.toStdString() << std::endl; | |
162 return 0; | |
163 } | |
164 | |
165 const DSSI_Descriptor *descriptor = 0; | |
166 | |
167 int index = 0; | |
168 while ((descriptor = fn(index))) { | |
169 if (descriptor->LADSPA_Plugin->Label == label) { | |
170 if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) { | |
171 descriptor->receive_host_descriptor(&m_hostDescriptor); | |
172 } | |
173 return descriptor; | |
174 } | |
175 ++index; | |
176 } | |
177 | |
178 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label.toStdString() << " in library " << soname.toStdString() << std::endl; | |
179 | |
180 return 0; | |
181 } | |
182 | |
183 const LADSPA_Descriptor * | |
184 DSSIPluginFactory::getLADSPADescriptor(QString identifier) | |
185 { | |
186 const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier); | |
187 if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin; | |
188 else return 0; | |
189 } | |
190 | |
191 | |
192 std::vector<QString> | |
193 DSSIPluginFactory::getPluginPath() | |
194 { | |
195 std::vector<QString> pathList; | |
196 std::string path; | |
197 | |
198 char *cpath = getenv("DSSI_PATH"); | |
199 if (cpath) path = cpath; | |
200 | |
201 if (path == "") { | |
202 path = "/usr/local/lib/dssi:/usr/lib/dssi"; | |
203 char *home = getenv("HOME"); | |
204 if (home) path = std::string(home) + "/.dssi:" + path; | |
205 } | |
206 | |
207 std::string::size_type index = 0, newindex = 0; | |
208 | |
209 while ((newindex = path.find(':', index)) < path.size()) { | |
210 pathList.push_back(path.substr(index, newindex - index).c_str()); | |
211 index = newindex + 1; | |
212 } | |
213 | |
214 pathList.push_back(path.substr(index).c_str()); | |
215 | |
216 return pathList; | |
217 } | |
218 | |
219 | |
220 #ifdef HAVE_LIBLRDF | |
221 std::vector<QString> | |
222 DSSIPluginFactory::getLRDFPath(QString &baseUri) | |
223 { | |
224 std::vector<QString> pathList = getPluginPath(); | |
225 std::vector<QString> lrdfPaths; | |
226 | |
227 lrdfPaths.push_back("/usr/local/share/dssi/rdf"); | |
228 lrdfPaths.push_back("/usr/share/dssi/rdf"); | |
229 | |
230 lrdfPaths.push_back("/usr/local/share/ladspa/rdf"); | |
231 lrdfPaths.push_back("/usr/share/ladspa/rdf"); | |
232 | |
233 for (std::vector<QString>::iterator i = pathList.begin(); | |
234 i != pathList.end(); ++i) { | |
235 lrdfPaths.push_back(*i + "/rdf"); | |
236 } | |
237 | |
238 #ifdef DSSI_BASE | |
239 baseUri = DSSI_BASE; | |
240 #else | |
241 baseUri = "http://dssi.sourceforge.net/ontology#"; | |
242 #endif | |
243 | |
244 return lrdfPaths; | |
245 } | |
246 #endif | |
247 | |
248 | |
249 void | |
250 DSSIPluginFactory::discoverPlugins(QString soname) | |
251 { | |
252 // Note that soname is expected to be a full path at this point, | |
253 // of a file that is known to exist | |
254 | |
255 void *libraryHandle = DLOPEN(soname, RTLD_LAZY); | |
256 | |
257 if (!libraryHandle) { | |
258 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library " | |
259 << soname.toStdString() << " - " << DLERROR() << std::endl; | |
260 return; | |
261 } | |
262 | |
263 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function) | |
264 DLSYM(libraryHandle, "dssi_descriptor"); | |
265 | |
266 if (!fn) { | |
267 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname.toStdString() << std::endl; | |
268 return; | |
269 } | |
270 | |
271 const DSSI_Descriptor *descriptor = 0; | |
272 | |
273 int index = 0; | |
274 while ((descriptor = fn(index))) { | |
275 | |
276 const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin; | |
277 if (!ladspaDescriptor) { | |
278 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname.toStdString() << std::endl; | |
279 ++index; | |
280 continue; | |
281 } | |
282 | |
283 #ifdef HAVE_LIBLRDF | |
284 char *def_uri = 0; | |
285 lrdf_defaults *defs = 0; | |
286 | |
287 QString category = m_taxonomy[ladspaDescriptor->UniqueID]; | |
288 | |
289 if (category == "" && ladspaDescriptor->Name != 0) { | |
290 std::string name = ladspaDescriptor->Name; | |
291 if (name.length() > 4 && | |
292 name.substr(name.length() - 4) == " VST") { | |
293 if (descriptor->run_synth || descriptor->run_multiple_synths) { | |
294 category = "VST instruments"; | |
295 } else { | |
296 category = "VST effects"; | |
297 } | |
298 m_taxonomy[ladspaDescriptor->UniqueID] = category; | |
299 } | |
300 } | |
301 | |
302 // std::cerr << "Plugin id is " << ladspaDescriptor->UniqueID | |
303 // << ", category is \"" << (category ? category : QString("(none)")) | |
304 // << "\", name is " << ladspaDescriptor->Name | |
305 // << ", label is " << ladspaDescriptor->Label | |
306 // << std::endl; | |
307 | |
308 def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID); | |
309 if (def_uri) { | |
310 defs = lrdf_get_setting_values(def_uri); | |
311 } | |
312 | |
313 int controlPortNumber = 1; | |
314 | |
315 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) { | |
316 | |
317 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) { | |
318 | |
319 if (def_uri && defs) { | |
320 | |
321 for (int j = 0; j < defs->count; j++) { | |
322 if (defs->items[j].pid == controlPortNumber) { | |
323 // 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; | |
324 m_portDefaults[ladspaDescriptor->UniqueID][i] = | |
325 defs->items[j].value; | |
326 } | |
327 } | |
328 } | |
329 | |
330 ++controlPortNumber; | |
331 } | |
332 } | |
333 #endif // HAVE_LIBLRDF | |
334 | |
335 QString identifier = PluginIdentifier::createIdentifier | |
336 ("dssi", soname, ladspaDescriptor->Label); | |
337 m_identifiers.push_back(identifier); | |
338 | |
339 ++index; | |
340 } | |
341 | |
342 if (DLCLOSE(libraryHandle) != 0) { | |
343 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << std::endl; | |
344 return; | |
345 } | |
346 } | |
347 | |
348 | |
349 |