Chris@49
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@52
|
4 Sonic Visualiser
|
Chris@52
|
5 An audio file viewer and annotation editor.
|
Chris@52
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@0
|
7
|
Chris@52
|
8 This program is free software; you can redistribute it and/or
|
Chris@52
|
9 modify it under the terms of the GNU General Public License as
|
Chris@52
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@52
|
11 License, or (at your option) any later version. See the file
|
Chris@52
|
12 COPYING included with this distribution for more information.
|
Chris@0
|
13 */
|
Chris@0
|
14
|
Chris@0
|
15 /*
|
Chris@0
|
16 This is a modified version of a source file from the
|
Chris@0
|
17 Rosegarden MIDI and audio sequencer and notation editor.
|
Chris@17
|
18 This file copyright 2000-2006 Chris Cannam.
|
Chris@0
|
19 */
|
Chris@0
|
20
|
Chris@0
|
21 #include <iostream>
|
Chris@0
|
22 #include <cassert>
|
Chris@0
|
23
|
Chris@0
|
24 #include "DSSIPluginInstance.h"
|
Chris@0
|
25 #include "PluginIdentifier.h"
|
Chris@0
|
26 #include "LADSPAPluginFactory.h"
|
Chris@0
|
27
|
Chris@405
|
28 #include <cstdlib>
|
Chris@405
|
29
|
Chris@608
|
30 #include <alloca.h>
|
Chris@608
|
31
|
Chris@117
|
32 //#define DEBUG_DSSI 1
|
Chris@0
|
33 //#define DEBUG_DSSI_PROCESS 1
|
Chris@0
|
34
|
Chris@0
|
35 #define EVENT_BUFFER_SIZE 1023
|
Chris@0
|
36
|
Chris@0
|
37 #ifdef DEBUG_DSSI
|
Chris@0
|
38 static std::ostream &operator<<(std::ostream& o, const QString &s)
|
Chris@0
|
39 {
|
Chris@0
|
40 o << s.toLocal8Bit().data();
|
Chris@0
|
41 return o;
|
Chris@0
|
42 }
|
Chris@0
|
43 #endif
|
Chris@0
|
44
|
Chris@0
|
45 DSSIPluginInstance::GroupMap DSSIPluginInstance::m_groupMap;
|
Chris@0
|
46 snd_seq_event_t **DSSIPluginInstance::m_groupLocalEventBuffers = 0;
|
Chris@0
|
47 size_t DSSIPluginInstance::m_groupLocalEventBufferCount = 0;
|
Chris@0
|
48 Scavenger<ScavengerArrayWrapper<snd_seq_event_t *> > DSSIPluginInstance::m_bufferScavenger(2, 10);
|
Chris@0
|
49 std::map<LADSPA_Handle, std::set<DSSIPluginInstance::NonRTPluginThread *> > DSSIPluginInstance::m_threads;
|
Chris@0
|
50
|
Chris@0
|
51
|
Chris@0
|
52 DSSIPluginInstance::DSSIPluginInstance(RealTimePluginFactory *factory,
|
Chris@0
|
53 int clientId,
|
Chris@0
|
54 QString identifier,
|
Chris@0
|
55 int position,
|
Chris@0
|
56 unsigned long sampleRate,
|
Chris@0
|
57 size_t blockSize,
|
Chris@0
|
58 int idealChannelCount,
|
Chris@0
|
59 const DSSI_Descriptor* descriptor) :
|
Chris@0
|
60 RealTimePluginInstance(factory, identifier),
|
Chris@0
|
61 m_client(clientId),
|
Chris@0
|
62 m_position(position),
|
Chris@0
|
63 m_descriptor(descriptor),
|
Chris@0
|
64 m_programCacheValid(false),
|
Chris@0
|
65 m_eventBuffer(EVENT_BUFFER_SIZE),
|
Chris@0
|
66 m_blockSize(blockSize),
|
Chris@0
|
67 m_idealChannelCount(idealChannelCount),
|
Chris@0
|
68 m_sampleRate(sampleRate),
|
Chris@0
|
69 m_latencyPort(0),
|
Chris@0
|
70 m_run(false),
|
Chris@0
|
71 m_bypassed(false),
|
Chris@10
|
72 m_grouped(false),
|
Chris@10
|
73 m_haveLastEventSendTime(false)
|
Chris@0
|
74 {
|
Chris@0
|
75 #ifdef DEBUG_DSSI
|
Chris@0
|
76 std::cerr << "DSSIPluginInstance::DSSIPluginInstance(" << identifier << ")"
|
Chris@0
|
77 << std::endl;
|
Chris@0
|
78 #endif
|
Chris@0
|
79
|
Chris@0
|
80 init();
|
Chris@0
|
81
|
Chris@0
|
82 m_inputBuffers = new sample_t*[m_audioPortsIn.size()];
|
Chris@0
|
83 m_outputBuffers = new sample_t*[m_outputBufferCount];
|
Chris@0
|
84
|
Chris@0
|
85 for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
|
Chris@0
|
86 m_inputBuffers[i] = new sample_t[blockSize];
|
Chris@0
|
87 }
|
Chris@0
|
88 for (size_t i = 0; i < m_outputBufferCount; ++i) {
|
Chris@0
|
89 m_outputBuffers[i] = new sample_t[blockSize];
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 m_ownBuffers = true;
|
Chris@0
|
93
|
Chris@0
|
94 m_pending.lsb = m_pending.msb = m_pending.program = -1;
|
Chris@0
|
95
|
Chris@0
|
96 instantiate(sampleRate);
|
Chris@0
|
97 if (isOK()) {
|
Chris@0
|
98 connectPorts();
|
Chris@0
|
99 activate();
|
Chris@0
|
100 initialiseGroupMembership();
|
Chris@0
|
101 }
|
Chris@0
|
102 }
|
Chris@0
|
103
|
Chris@51
|
104 std::string
|
Chris@239
|
105 DSSIPluginInstance::getIdentifier() const
|
Chris@239
|
106 {
|
Chris@239
|
107 return m_descriptor->LADSPA_Plugin->Label;
|
Chris@239
|
108 }
|
Chris@239
|
109
|
Chris@239
|
110 std::string
|
Chris@51
|
111 DSSIPluginInstance::getName() const
|
Chris@0
|
112 {
|
Chris@239
|
113 return m_descriptor->LADSPA_Plugin->Name;
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@51
|
116 std::string
|
Chris@51
|
117 DSSIPluginInstance::getDescription() const
|
Chris@51
|
118 {
|
Chris@239
|
119 return "";
|
Chris@51
|
120 }
|
Chris@51
|
121
|
Chris@51
|
122 std::string
|
Chris@51
|
123 DSSIPluginInstance::getMaker() const
|
Chris@51
|
124 {
|
Chris@51
|
125 return m_descriptor->LADSPA_Plugin->Maker;
|
Chris@51
|
126 }
|
Chris@51
|
127
|
Chris@51
|
128 int
|
Chris@51
|
129 DSSIPluginInstance::getPluginVersion() const
|
Chris@51
|
130 {
|
Chris@473
|
131 return -1;
|
Chris@51
|
132 }
|
Chris@51
|
133
|
Chris@51
|
134 std::string
|
Chris@51
|
135 DSSIPluginInstance::getCopyright() const
|
Chris@51
|
136 {
|
Chris@51
|
137 return m_descriptor->LADSPA_Plugin->Copyright;
|
Chris@51
|
138 }
|
Chris@51
|
139
|
Chris@51
|
140 DSSIPluginInstance::ParameterList
|
Chris@51
|
141 DSSIPluginInstance::getParameterDescriptors() const
|
Chris@51
|
142 {
|
Chris@51
|
143 ParameterList list;
|
Chris@51
|
144 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@51
|
145
|
Chris@51
|
146 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@51
|
147
|
Chris@51
|
148 ParameterDescriptor pd;
|
Chris@51
|
149 unsigned int pn = m_controlPortsIn[i].first;
|
Chris@51
|
150
|
Chris@239
|
151 pd.identifier = m_descriptor->LADSPA_Plugin->PortNames[pn];
|
Chris@239
|
152 pd.name = pd.identifier;
|
Chris@239
|
153 pd.description = "";
|
Chris@51
|
154 pd.minValue = f->getPortMinimum(m_descriptor->LADSPA_Plugin, pn);
|
Chris@51
|
155 pd.maxValue = f->getPortMaximum(m_descriptor->LADSPA_Plugin, pn);
|
Chris@51
|
156 pd.defaultValue = f->getPortDefault(m_descriptor->LADSPA_Plugin, pn);
|
Chris@57
|
157
|
Chris@57
|
158 float q = f->getPortQuantization(m_descriptor->LADSPA_Plugin, pn);
|
Chris@57
|
159 if (q == 0.0) {
|
Chris@57
|
160 pd.isQuantized = false;
|
Chris@57
|
161 } else {
|
Chris@57
|
162 pd.isQuantized = true;
|
Chris@57
|
163 pd.quantizeStep = q;
|
Chris@57
|
164 }
|
Chris@51
|
165
|
Chris@51
|
166 list.push_back(pd);
|
Chris@51
|
167 }
|
Chris@51
|
168
|
Chris@51
|
169 return list;
|
Chris@51
|
170 }
|
Chris@51
|
171
|
Chris@51
|
172 float
|
Chris@239
|
173 DSSIPluginInstance::getParameter(std::string id) const
|
Chris@51
|
174 {
|
Chris@117
|
175 #ifdef DEBUG_DSSI
|
Chris@239
|
176 std::cerr << "DSSIPluginInstance::getParameter(" << id << ")" << std::endl;
|
Chris@117
|
177 #endif
|
Chris@51
|
178 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@239
|
179 if (id == m_descriptor->LADSPA_Plugin->PortNames[m_controlPortsIn[i].first]) {
|
Chris@117
|
180 #ifdef DEBUG_DSSI
|
Chris@57
|
181 std::cerr << "Matches port " << i << std::endl;
|
Chris@117
|
182 #endif
|
Chris@57
|
183 float v = getParameterValue(i);
|
Chris@117
|
184 #ifdef DEBUG_DSSI
|
Chris@57
|
185 std::cerr << "Returning " << v << std::endl;
|
Chris@117
|
186 #endif
|
Chris@57
|
187 return v;
|
Chris@51
|
188 }
|
Chris@51
|
189 }
|
Chris@51
|
190
|
Chris@51
|
191 return 0.0;
|
Chris@51
|
192 }
|
Chris@51
|
193
|
Chris@51
|
194 void
|
Chris@239
|
195 DSSIPluginInstance::setParameter(std::string id, float value)
|
Chris@51
|
196 {
|
Chris@117
|
197 #ifdef DEBUG_DSSI
|
Chris@239
|
198 std::cerr << "DSSIPluginInstance::setParameter(" << id << ", " << value << ")" << std::endl;
|
Chris@117
|
199 #endif
|
Chris@57
|
200
|
Chris@51
|
201 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@239
|
202 if (id == m_descriptor->LADSPA_Plugin->PortNames[m_controlPortsIn[i].first]) {
|
Chris@51
|
203 setParameterValue(i, value);
|
Chris@51
|
204 break;
|
Chris@51
|
205 }
|
Chris@51
|
206 }
|
Chris@51
|
207 }
|
Chris@0
|
208
|
Chris@0
|
209 void
|
Chris@0
|
210 DSSIPluginInstance::init()
|
Chris@0
|
211 {
|
Chris@0
|
212 #ifdef DEBUG_DSSI
|
Chris@0
|
213 std::cerr << "DSSIPluginInstance::init" << std::endl;
|
Chris@0
|
214 #endif
|
Chris@0
|
215
|
Chris@0
|
216 // Discover ports numbers and identities
|
Chris@0
|
217 //
|
Chris@0
|
218 const LADSPA_Descriptor *descriptor = m_descriptor->LADSPA_Plugin;
|
Chris@0
|
219
|
Chris@0
|
220 for (unsigned long i = 0; i < descriptor->PortCount; ++i)
|
Chris@0
|
221 {
|
Chris@0
|
222 if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[i]))
|
Chris@0
|
223 {
|
Chris@0
|
224 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
|
Chris@0
|
225 m_audioPortsIn.push_back(i);
|
Chris@0
|
226 } else {
|
Chris@0
|
227 m_audioPortsOut.push_back(i);
|
Chris@0
|
228 }
|
Chris@0
|
229 }
|
Chris@0
|
230 else
|
Chris@0
|
231 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]))
|
Chris@0
|
232 {
|
Chris@0
|
233 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
|
Chris@0
|
234
|
Chris@0
|
235 LADSPA_Data *data = new LADSPA_Data(0.0);
|
Chris@0
|
236
|
Chris@0
|
237 m_controlPortsIn.push_back(std::pair<unsigned long, LADSPA_Data*>
|
Chris@0
|
238 (i, data));
|
Chris@0
|
239
|
Chris@0
|
240 m_backupControlPortsIn.push_back(0.0);
|
Chris@0
|
241
|
Chris@0
|
242 } else {
|
Chris@0
|
243 LADSPA_Data *data = new LADSPA_Data(0.0);
|
Chris@0
|
244 m_controlPortsOut.push_back(
|
Chris@0
|
245 std::pair<unsigned long, LADSPA_Data*>(i, data));
|
Chris@0
|
246 if (!strcmp(descriptor->PortNames[i], "latency") ||
|
Chris@0
|
247 !strcmp(descriptor->PortNames[i], "_latency")) {
|
Chris@0
|
248 #ifdef DEBUG_DSSI
|
Chris@0
|
249 std::cerr << "Wooo! We have a latency port!" << std::endl;
|
Chris@0
|
250 #endif
|
Chris@0
|
251 m_latencyPort = data;
|
Chris@0
|
252 }
|
Chris@0
|
253 }
|
Chris@0
|
254 }
|
Chris@0
|
255 #ifdef DEBUG_DSSI
|
Chris@0
|
256 else
|
Chris@0
|
257 std::cerr << "DSSIPluginInstance::DSSIPluginInstance - "
|
Chris@0
|
258 << "unrecognised port type" << std::endl;
|
Chris@0
|
259 #endif
|
Chris@0
|
260 }
|
Chris@0
|
261
|
Chris@0
|
262 m_outputBufferCount = std::max(m_idealChannelCount, m_audioPortsOut.size());
|
Chris@0
|
263 }
|
Chris@0
|
264
|
Chris@0
|
265 size_t
|
Chris@0
|
266 DSSIPluginInstance::getLatency()
|
Chris@0
|
267 {
|
Chris@0
|
268 size_t latency = 0;
|
Chris@0
|
269
|
Chris@0
|
270 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
271 std::cerr << "DSSIPluginInstance::getLatency(): m_latencyPort " << m_latencyPort << ", m_run " << m_run << std::endl;
|
Chris@0
|
272 #endif
|
Chris@0
|
273
|
Chris@0
|
274 if (m_latencyPort) {
|
Chris@242
|
275 if (!m_run) {
|
Chris@259
|
276 for (size_t i = 0; i < getAudioInputCount(); ++i) {
|
Chris@259
|
277 for (size_t j = 0; j < m_blockSize; ++j) {
|
Chris@242
|
278 m_inputBuffers[i][j] = 0.f;
|
Chris@242
|
279 }
|
Chris@242
|
280 }
|
Chris@242
|
281 run(Vamp::RealTime::zeroTime);
|
Chris@242
|
282 }
|
Chris@0
|
283 latency = (size_t)(*m_latencyPort + 0.1);
|
Chris@0
|
284 }
|
Chris@0
|
285
|
Chris@0
|
286 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
287 std::cerr << "DSSIPluginInstance::getLatency(): latency is " << latency << std::endl;
|
Chris@0
|
288 #endif
|
Chris@0
|
289
|
Chris@0
|
290 return latency;
|
Chris@0
|
291 }
|
Chris@0
|
292
|
Chris@0
|
293 void
|
Chris@0
|
294 DSSIPluginInstance::silence()
|
Chris@0
|
295 {
|
Chris@0
|
296 if (m_instanceHandle != 0) {
|
Chris@0
|
297 deactivate();
|
Chris@0
|
298 activate();
|
Chris@0
|
299 }
|
Chris@0
|
300 }
|
Chris@0
|
301
|
Chris@0
|
302 void
|
Chris@0
|
303 DSSIPluginInstance::discardEvents()
|
Chris@0
|
304 {
|
Chris@0
|
305 m_eventBuffer.reset();
|
Chris@0
|
306 }
|
Chris@0
|
307
|
Chris@0
|
308 void
|
Chris@0
|
309 DSSIPluginInstance::setIdealChannelCount(size_t channels)
|
Chris@0
|
310 {
|
Chris@0
|
311 #ifdef DEBUG_DSSI
|
Chris@0
|
312 std::cerr << "DSSIPluginInstance::setIdealChannelCount: channel count "
|
Chris@0
|
313 << channels << " (was " << m_idealChannelCount << ")" << std::endl;
|
Chris@0
|
314 #endif
|
Chris@0
|
315
|
Chris@0
|
316 if (channels == m_idealChannelCount) {
|
Chris@0
|
317 silence();
|
Chris@0
|
318 return;
|
Chris@0
|
319 }
|
Chris@0
|
320
|
Chris@0
|
321 if (m_instanceHandle != 0) {
|
Chris@0
|
322 deactivate();
|
Chris@0
|
323 }
|
Chris@0
|
324
|
Chris@0
|
325 m_idealChannelCount = channels;
|
Chris@0
|
326
|
Chris@0
|
327 if (channels > m_outputBufferCount) {
|
Chris@0
|
328
|
Chris@0
|
329 for (size_t i = 0; i < m_outputBufferCount; ++i) {
|
Chris@0
|
330 delete[] m_outputBuffers[i];
|
Chris@0
|
331 }
|
Chris@0
|
332
|
Chris@0
|
333 delete[] m_outputBuffers;
|
Chris@0
|
334
|
Chris@0
|
335 m_outputBufferCount = channels;
|
Chris@0
|
336
|
Chris@0
|
337 m_outputBuffers = new sample_t*[m_outputBufferCount];
|
Chris@0
|
338
|
Chris@0
|
339 for (size_t i = 0; i < m_outputBufferCount; ++i) {
|
Chris@0
|
340 m_outputBuffers[i] = new sample_t[m_blockSize];
|
Chris@0
|
341 }
|
Chris@0
|
342
|
Chris@0
|
343 connectPorts();
|
Chris@0
|
344 }
|
Chris@0
|
345
|
Chris@0
|
346 if (m_instanceHandle != 0) {
|
Chris@0
|
347 activate();
|
Chris@0
|
348 }
|
Chris@0
|
349 }
|
Chris@0
|
350
|
Chris@0
|
351 void
|
Chris@0
|
352 DSSIPluginInstance::detachFromGroup()
|
Chris@0
|
353 {
|
Chris@0
|
354 if (!m_grouped) return;
|
Chris@0
|
355 m_groupMap[m_identifier].erase(this);
|
Chris@0
|
356 m_grouped = false;
|
Chris@0
|
357 }
|
Chris@0
|
358
|
Chris@0
|
359 void
|
Chris@0
|
360 DSSIPluginInstance::initialiseGroupMembership()
|
Chris@0
|
361 {
|
Chris@0
|
362 if (!m_descriptor->run_multiple_synths) {
|
Chris@0
|
363 m_grouped = false;
|
Chris@0
|
364 return;
|
Chris@0
|
365 }
|
Chris@0
|
366
|
Chris@0
|
367 //!!! GroupMap is not actually thread-safe.
|
Chris@0
|
368
|
Chris@0
|
369 size_t pluginsInGroup = m_groupMap[m_identifier].size();
|
Chris@0
|
370
|
Chris@0
|
371 if (++pluginsInGroup > m_groupLocalEventBufferCount) {
|
Chris@0
|
372
|
Chris@0
|
373 size_t nextBufferCount = pluginsInGroup * 2;
|
Chris@0
|
374
|
Chris@0
|
375 snd_seq_event_t **eventLocalBuffers = new snd_seq_event_t *[nextBufferCount];
|
Chris@0
|
376
|
Chris@0
|
377 for (size_t i = 0; i < m_groupLocalEventBufferCount; ++i) {
|
Chris@0
|
378 eventLocalBuffers[i] = m_groupLocalEventBuffers[i];
|
Chris@0
|
379 }
|
Chris@0
|
380 for (size_t i = m_groupLocalEventBufferCount; i < nextBufferCount; ++i) {
|
Chris@0
|
381 eventLocalBuffers[i] = new snd_seq_event_t[EVENT_BUFFER_SIZE];
|
Chris@0
|
382 }
|
Chris@0
|
383
|
Chris@0
|
384 if (m_groupLocalEventBuffers) {
|
Chris@0
|
385 m_bufferScavenger.claim(new ScavengerArrayWrapper<snd_seq_event_t *>
|
Chris@0
|
386 (m_groupLocalEventBuffers));
|
Chris@0
|
387 }
|
Chris@0
|
388
|
Chris@0
|
389 m_groupLocalEventBuffers = eventLocalBuffers;
|
Chris@0
|
390 m_groupLocalEventBufferCount = nextBufferCount;
|
Chris@0
|
391 }
|
Chris@0
|
392
|
Chris@0
|
393 m_grouped = true;
|
Chris@0
|
394 m_groupMap[m_identifier].insert(this);
|
Chris@0
|
395 }
|
Chris@0
|
396
|
Chris@0
|
397 DSSIPluginInstance::~DSSIPluginInstance()
|
Chris@0
|
398 {
|
Chris@117
|
399 #ifdef DEBUG_DSSI
|
Chris@0
|
400 std::cerr << "DSSIPluginInstance::~DSSIPluginInstance" << std::endl;
|
Chris@117
|
401 #endif
|
Chris@0
|
402
|
Chris@0
|
403 if (m_threads.find(m_instanceHandle) != m_threads.end()) {
|
Chris@0
|
404
|
Chris@0
|
405 for (std::set<NonRTPluginThread *>::iterator i =
|
Chris@0
|
406 m_threads[m_instanceHandle].begin();
|
Chris@0
|
407 i != m_threads[m_instanceHandle].end(); ++i) {
|
Chris@0
|
408
|
Chris@0
|
409 (*i)->setExiting();
|
Chris@0
|
410 (*i)->wait();
|
Chris@0
|
411 delete *i;
|
Chris@0
|
412 }
|
Chris@0
|
413
|
Chris@0
|
414 m_threads.erase(m_instanceHandle);
|
Chris@0
|
415 }
|
Chris@0
|
416
|
Chris@0
|
417 detachFromGroup();
|
Chris@0
|
418
|
Chris@0
|
419 if (m_instanceHandle != 0) {
|
Chris@0
|
420 deactivate();
|
Chris@0
|
421 }
|
Chris@0
|
422
|
Chris@0
|
423 cleanup();
|
Chris@0
|
424
|
Chris@0
|
425 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i)
|
Chris@0
|
426 delete m_controlPortsIn[i].second;
|
Chris@0
|
427
|
Chris@0
|
428 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i)
|
Chris@0
|
429 delete m_controlPortsOut[i].second;
|
Chris@0
|
430
|
Chris@0
|
431 m_controlPortsIn.clear();
|
Chris@0
|
432 m_controlPortsOut.clear();
|
Chris@0
|
433
|
Chris@0
|
434 if (m_ownBuffers) {
|
Chris@0
|
435 for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
|
Chris@0
|
436 delete[] m_inputBuffers[i];
|
Chris@0
|
437 }
|
Chris@0
|
438 for (size_t i = 0; i < m_outputBufferCount; ++i) {
|
Chris@0
|
439 delete[] m_outputBuffers[i];
|
Chris@0
|
440 }
|
Chris@0
|
441
|
Chris@0
|
442 delete[] m_inputBuffers;
|
Chris@0
|
443 delete[] m_outputBuffers;
|
Chris@0
|
444 }
|
Chris@0
|
445
|
Chris@0
|
446 m_audioPortsIn.clear();
|
Chris@0
|
447 m_audioPortsOut.clear();
|
Chris@0
|
448 }
|
Chris@0
|
449
|
Chris@0
|
450
|
Chris@0
|
451 void
|
Chris@0
|
452 DSSIPluginInstance::instantiate(unsigned long sampleRate)
|
Chris@0
|
453 {
|
Chris@0
|
454 #ifdef DEBUG_DSSI
|
Chris@0
|
455 std::cout << "DSSIPluginInstance::instantiate - plugin \"unique\" id = "
|
Chris@0
|
456 << m_descriptor->LADSPA_Plugin->UniqueID << std::endl;
|
Chris@0
|
457 #endif
|
Chris@0
|
458 if (!m_descriptor) return;
|
Chris@0
|
459
|
Chris@0
|
460 const LADSPA_Descriptor *descriptor = m_descriptor->LADSPA_Plugin;
|
Chris@0
|
461
|
Chris@0
|
462 if (!descriptor->instantiate) {
|
Chris@0
|
463 std::cerr << "Bad plugin: plugin id " << descriptor->UniqueID
|
Chris@0
|
464 << ":" << descriptor->Label
|
Chris@0
|
465 << " has no instantiate method!" << std::endl;
|
Chris@0
|
466 return;
|
Chris@0
|
467 }
|
Chris@0
|
468
|
Chris@0
|
469 m_instanceHandle = descriptor->instantiate(descriptor, sampleRate);
|
Chris@0
|
470
|
Chris@0
|
471 if (m_instanceHandle) {
|
Chris@0
|
472
|
Chris@0
|
473 if (m_descriptor->get_midi_controller_for_port) {
|
Chris@0
|
474
|
Chris@0
|
475 for (unsigned long i = 0; i < descriptor->PortCount; ++i) {
|
Chris@0
|
476
|
Chris@0
|
477 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i]) &&
|
Chris@0
|
478 LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i])) {
|
Chris@0
|
479
|
Chris@0
|
480 int controller = m_descriptor->get_midi_controller_for_port
|
Chris@0
|
481 (m_instanceHandle, i);
|
Chris@0
|
482
|
Chris@0
|
483 if (controller != 0 && controller != 32 &&
|
Chris@0
|
484 DSSI_IS_CC(controller)) {
|
Chris@0
|
485
|
Chris@0
|
486 m_controllerMap[DSSI_CC_NUMBER(controller)] = i;
|
Chris@0
|
487 }
|
Chris@0
|
488 }
|
Chris@0
|
489 }
|
Chris@0
|
490 }
|
Chris@0
|
491 }
|
Chris@0
|
492 }
|
Chris@0
|
493
|
Chris@0
|
494 void
|
Chris@0
|
495 DSSIPluginInstance::checkProgramCache() const
|
Chris@0
|
496 {
|
Chris@0
|
497 if (m_programCacheValid) return;
|
Chris@0
|
498 m_cachedPrograms.clear();
|
Chris@0
|
499
|
Chris@0
|
500 #ifdef DEBUG_DSSI
|
Chris@0
|
501 std::cerr << "DSSIPluginInstance::checkProgramCache" << std::endl;
|
Chris@0
|
502 #endif
|
Chris@0
|
503
|
Chris@0
|
504 if (!m_descriptor || !m_descriptor->get_program) {
|
Chris@0
|
505 m_programCacheValid = true;
|
Chris@0
|
506 return;
|
Chris@0
|
507 }
|
Chris@0
|
508
|
Chris@0
|
509 unsigned long index = 0;
|
Chris@0
|
510 const DSSI_Program_Descriptor *programDescriptor;
|
Chris@0
|
511 while ((programDescriptor = m_descriptor->get_program(m_instanceHandle, index))) {
|
Chris@0
|
512 ++index;
|
Chris@0
|
513 ProgramDescriptor d;
|
Chris@0
|
514 d.bank = programDescriptor->Bank;
|
Chris@0
|
515 d.program = programDescriptor->Program;
|
Chris@0
|
516 d.name = programDescriptor->Name;
|
Chris@0
|
517 m_cachedPrograms.push_back(d);
|
Chris@0
|
518 }
|
Chris@0
|
519
|
Chris@0
|
520 #ifdef DEBUG_DSSI
|
Chris@0
|
521 std::cerr << "DSSIPluginInstance::checkProgramCache: have " << m_cachedPrograms.size() << " programs" << std::endl;
|
Chris@0
|
522 #endif
|
Chris@0
|
523
|
Chris@0
|
524 m_programCacheValid = true;
|
Chris@0
|
525 }
|
Chris@0
|
526
|
Chris@51
|
527 DSSIPluginInstance::ProgramList
|
Chris@0
|
528 DSSIPluginInstance::getPrograms() const
|
Chris@0
|
529 {
|
Chris@0
|
530 #ifdef DEBUG_DSSI
|
Chris@0
|
531 std::cerr << "DSSIPluginInstance::getPrograms" << std::endl;
|
Chris@0
|
532 #endif
|
Chris@0
|
533
|
Chris@51
|
534 if (!m_descriptor) return ProgramList();
|
Chris@0
|
535
|
Chris@0
|
536 checkProgramCache();
|
Chris@0
|
537
|
Chris@51
|
538 ProgramList programs;
|
Chris@0
|
539
|
Chris@0
|
540 for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
|
Chris@0
|
541 i != m_cachedPrograms.end(); ++i) {
|
Chris@0
|
542 programs.push_back(i->name);
|
Chris@0
|
543 }
|
Chris@0
|
544
|
Chris@0
|
545 return programs;
|
Chris@0
|
546 }
|
Chris@0
|
547
|
Chris@51
|
548 std::string
|
Chris@0
|
549 DSSIPluginInstance::getProgram(int bank, int program) const
|
Chris@0
|
550 {
|
Chris@0
|
551 #ifdef DEBUG_DSSI
|
Chris@0
|
552 std::cerr << "DSSIPluginInstance::getProgram(" << bank << "," << program << ")" << std::endl;
|
Chris@0
|
553 #endif
|
Chris@0
|
554
|
Chris@51
|
555 if (!m_descriptor) return std::string();
|
Chris@0
|
556
|
Chris@0
|
557 checkProgramCache();
|
Chris@0
|
558
|
Chris@0
|
559 for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
|
Chris@0
|
560 i != m_cachedPrograms.end(); ++i) {
|
Chris@0
|
561 if (i->bank == bank && i->program == program) return i->name;
|
Chris@0
|
562 }
|
Chris@0
|
563
|
Chris@51
|
564 return std::string();
|
Chris@0
|
565 }
|
Chris@0
|
566
|
Chris@0
|
567 unsigned long
|
Chris@51
|
568 DSSIPluginInstance::getProgram(std::string name) const
|
Chris@0
|
569 {
|
Chris@0
|
570 #ifdef DEBUG_DSSI
|
Chris@0
|
571 std::cerr << "DSSIPluginInstance::getProgram(" << name << ")" << std::endl;
|
Chris@0
|
572 #endif
|
Chris@0
|
573
|
Chris@0
|
574 if (!m_descriptor) return 0;
|
Chris@0
|
575
|
Chris@0
|
576 checkProgramCache();
|
Chris@0
|
577
|
Chris@0
|
578 unsigned long rv;
|
Chris@0
|
579
|
Chris@0
|
580 for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
|
Chris@0
|
581 i != m_cachedPrograms.end(); ++i) {
|
Chris@0
|
582 if (i->name == name) {
|
Chris@0
|
583 rv = i->bank;
|
Chris@0
|
584 rv = (rv << 16) + i->program;
|
Chris@0
|
585 return rv;
|
Chris@0
|
586 }
|
Chris@0
|
587 }
|
Chris@0
|
588
|
Chris@0
|
589 return 0;
|
Chris@0
|
590 }
|
Chris@0
|
591
|
Chris@51
|
592 std::string
|
Chris@0
|
593 DSSIPluginInstance::getCurrentProgram() const
|
Chris@0
|
594 {
|
Chris@0
|
595 return m_program;
|
Chris@0
|
596 }
|
Chris@0
|
597
|
Chris@0
|
598 void
|
Chris@51
|
599 DSSIPluginInstance::selectProgram(std::string program)
|
Chris@0
|
600 {
|
Chris@0
|
601 selectProgramAux(program, true);
|
Chris@0
|
602 }
|
Chris@0
|
603
|
Chris@0
|
604 void
|
Chris@51
|
605 DSSIPluginInstance::selectProgramAux(std::string program, bool backupPortValues)
|
Chris@0
|
606 {
|
Chris@0
|
607 #ifdef DEBUG_DSSI
|
Chris@0
|
608 std::cerr << "DSSIPluginInstance::selectProgram(" << program << ")" << std::endl;
|
Chris@0
|
609 #endif
|
Chris@0
|
610
|
Chris@0
|
611 if (!m_descriptor) return;
|
Chris@0
|
612
|
Chris@0
|
613 checkProgramCache();
|
Chris@0
|
614
|
Chris@0
|
615 if (!m_descriptor->select_program) return;
|
Chris@0
|
616
|
Chris@0
|
617 bool found = false;
|
Chris@0
|
618 unsigned long bankNo = 0, programNo = 0;
|
Chris@0
|
619
|
Chris@0
|
620 for (std::vector<ProgramDescriptor>::iterator i = m_cachedPrograms.begin();
|
Chris@0
|
621 i != m_cachedPrograms.end(); ++i) {
|
Chris@0
|
622
|
Chris@0
|
623 if (i->name == program) {
|
Chris@0
|
624
|
Chris@0
|
625 bankNo = i->bank;
|
Chris@0
|
626 programNo = i->program;
|
Chris@0
|
627 found = true;
|
Chris@0
|
628
|
Chris@0
|
629 #ifdef DEBUG_DSSI
|
Chris@0
|
630 std::cerr << "DSSIPluginInstance::selectProgram(" << program << "): found at bank " << bankNo << ", program " << programNo << std::endl;
|
Chris@0
|
631 #endif
|
Chris@0
|
632
|
Chris@0
|
633 break;
|
Chris@0
|
634 }
|
Chris@0
|
635 }
|
Chris@0
|
636
|
Chris@0
|
637 if (!found) return;
|
Chris@0
|
638 m_program = program;
|
Chris@0
|
639
|
Chris@0
|
640 // DSSI select_program is an audio context call
|
Chris@0
|
641 m_processLock.lock();
|
Chris@0
|
642 m_descriptor->select_program(m_instanceHandle, bankNo, programNo);
|
Chris@0
|
643 m_processLock.unlock();
|
Chris@0
|
644
|
Chris@0
|
645 #ifdef DEBUG_DSSI
|
Chris@0
|
646 std::cerr << "DSSIPluginInstance::selectProgram(" << program << "): made select_program(" << bankNo << "," << programNo << ") call" << std::endl;
|
Chris@0
|
647 #endif
|
Chris@0
|
648
|
Chris@0
|
649 if (backupPortValues) {
|
Chris@0
|
650 for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
|
Chris@0
|
651 m_backupControlPortsIn[i] = *m_controlPortsIn[i].second;
|
Chris@0
|
652 }
|
Chris@0
|
653 }
|
Chris@0
|
654 }
|
Chris@0
|
655
|
Chris@0
|
656 void
|
Chris@0
|
657 DSSIPluginInstance::activate()
|
Chris@0
|
658 {
|
Chris@0
|
659 #ifdef DEBUG_DSSI
|
Chris@0
|
660 std::cerr << "DSSIPluginInstance::activate" << std::endl;
|
Chris@0
|
661 #endif
|
Chris@0
|
662
|
Chris@0
|
663 if (!m_descriptor || !m_descriptor->LADSPA_Plugin->activate) return;
|
Chris@0
|
664 m_descriptor->LADSPA_Plugin->activate(m_instanceHandle);
|
Chris@0
|
665
|
Chris@51
|
666 if (m_program != "") {
|
Chris@0
|
667 #ifdef DEBUG_DSSI
|
Chris@0
|
668 std::cerr << "DSSIPluginInstance::activate: restoring program " << m_program << std::endl;
|
Chris@0
|
669 #endif
|
Chris@0
|
670 selectProgramAux(m_program, false);
|
Chris@0
|
671 }
|
Chris@0
|
672
|
Chris@0
|
673 for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
|
Chris@0
|
674 #ifdef DEBUG_DSSI
|
Chris@0
|
675 std::cerr << "DSSIPluginInstance::activate: setting port " << m_controlPortsIn[i].first << " to " << m_backupControlPortsIn[i] << std::endl;
|
Chris@0
|
676 #endif
|
Chris@0
|
677 *m_controlPortsIn[i].second = m_backupControlPortsIn[i];
|
Chris@0
|
678 }
|
Chris@0
|
679 }
|
Chris@0
|
680
|
Chris@0
|
681 void
|
Chris@0
|
682 DSSIPluginInstance::connectPorts()
|
Chris@0
|
683 {
|
Chris@0
|
684 if (!m_descriptor || !m_descriptor->LADSPA_Plugin->connect_port) return;
|
Chris@117
|
685 #ifdef DEBUG_DSSI
|
Chris@0
|
686 std::cerr << "DSSIPluginInstance::connectPorts: " << m_audioPortsIn.size()
|
Chris@0
|
687 << " audio ports in, " << m_audioPortsOut.size() << " out, "
|
Chris@0
|
688 << m_outputBufferCount << " output buffers" << std::endl;
|
Chris@117
|
689 #endif
|
Chris@0
|
690
|
Chris@0
|
691 assert(sizeof(LADSPA_Data) == sizeof(float));
|
Chris@0
|
692 assert(sizeof(sample_t) == sizeof(float));
|
Chris@57
|
693
|
Chris@57
|
694 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@0
|
695 int inbuf = 0, outbuf = 0;
|
Chris@0
|
696
|
Chris@0
|
697 for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) {
|
Chris@0
|
698 m_descriptor->LADSPA_Plugin->connect_port
|
Chris@0
|
699 (m_instanceHandle,
|
Chris@0
|
700 m_audioPortsIn[i],
|
Chris@0
|
701 (LADSPA_Data *)m_inputBuffers[inbuf]);
|
Chris@0
|
702 ++inbuf;
|
Chris@0
|
703 }
|
Chris@0
|
704
|
Chris@0
|
705 for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) {
|
Chris@0
|
706 m_descriptor->LADSPA_Plugin->connect_port
|
Chris@0
|
707 (m_instanceHandle,
|
Chris@0
|
708 m_audioPortsOut[i],
|
Chris@0
|
709 (LADSPA_Data *)m_outputBuffers[outbuf]);
|
Chris@0
|
710 ++outbuf;
|
Chris@0
|
711 }
|
Chris@0
|
712
|
Chris@0
|
713 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@0
|
714 m_descriptor->LADSPA_Plugin->connect_port
|
Chris@0
|
715 (m_instanceHandle,
|
Chris@0
|
716 m_controlPortsIn[i].first,
|
Chris@0
|
717 m_controlPortsIn[i].second);
|
Chris@57
|
718
|
Chris@57
|
719 if (f) {
|
Chris@57
|
720 float defaultValue = f->getPortDefault
|
Chris@57
|
721 (m_descriptor->LADSPA_Plugin, m_controlPortsIn[i].first);
|
Chris@57
|
722 *m_controlPortsIn[i].second = defaultValue;
|
Chris@57
|
723 m_backupControlPortsIn[i] = defaultValue;
|
Chris@117
|
724 #ifdef DEBUG_DSSI
|
Chris@57
|
725 std::cerr << "DSSIPluginInstance::connectPorts: set control port " << i << " to default value " << defaultValue << std::endl;
|
Chris@117
|
726 #endif
|
Chris@57
|
727 }
|
Chris@0
|
728 }
|
Chris@0
|
729
|
Chris@0
|
730 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) {
|
Chris@0
|
731 m_descriptor->LADSPA_Plugin->connect_port
|
Chris@0
|
732 (m_instanceHandle,
|
Chris@0
|
733 m_controlPortsOut[i].first,
|
Chris@0
|
734 m_controlPortsOut[i].second);
|
Chris@0
|
735 }
|
Chris@0
|
736 }
|
Chris@0
|
737
|
Chris@0
|
738 unsigned int
|
Chris@0
|
739 DSSIPluginInstance::getParameterCount() const
|
Chris@0
|
740 {
|
Chris@0
|
741 return m_controlPortsIn.size();
|
Chris@0
|
742 }
|
Chris@0
|
743
|
Chris@0
|
744 void
|
Chris@0
|
745 DSSIPluginInstance::setParameterValue(unsigned int parameter, float value)
|
Chris@0
|
746 {
|
Chris@0
|
747 #ifdef DEBUG_DSSI
|
Chris@0
|
748 std::cerr << "DSSIPluginInstance::setParameterValue(" << parameter << ") to " << value << std::endl;
|
Chris@0
|
749 #endif
|
Chris@0
|
750 if (parameter >= m_controlPortsIn.size()) return;
|
Chris@0
|
751
|
Chris@0
|
752 unsigned int portNumber = m_controlPortsIn[parameter].first;
|
Chris@0
|
753
|
Chris@0
|
754 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@0
|
755 if (f) {
|
Chris@0
|
756 if (value < f->getPortMinimum(m_descriptor->LADSPA_Plugin, portNumber)) {
|
Chris@0
|
757 value = f->getPortMinimum(m_descriptor->LADSPA_Plugin, portNumber);
|
Chris@0
|
758 }
|
Chris@0
|
759 if (value > f->getPortMaximum(m_descriptor->LADSPA_Plugin, portNumber)) {
|
Chris@0
|
760 value = f->getPortMaximum(m_descriptor->LADSPA_Plugin, portNumber);
|
Chris@0
|
761 }
|
Chris@0
|
762 }
|
Chris@0
|
763
|
Chris@0
|
764 (*m_controlPortsIn[parameter].second) = value;
|
Chris@0
|
765 m_backupControlPortsIn[parameter] = value;
|
Chris@0
|
766 }
|
Chris@0
|
767
|
Chris@0
|
768 void
|
Chris@0
|
769 DSSIPluginInstance::setPortValueFromController(unsigned int port, int cv)
|
Chris@0
|
770 {
|
Chris@0
|
771 #ifdef DEBUG_DSSI
|
Chris@0
|
772 std::cerr << "DSSIPluginInstance::setPortValueFromController(" << port << ") to " << cv << std::endl;
|
Chris@0
|
773 #endif
|
Chris@0
|
774
|
Chris@0
|
775 const LADSPA_Descriptor *p = m_descriptor->LADSPA_Plugin;
|
Chris@0
|
776 LADSPA_PortRangeHintDescriptor d = p->PortRangeHints[port].HintDescriptor;
|
Chris@0
|
777 LADSPA_Data lb = p->PortRangeHints[port].LowerBound;
|
Chris@0
|
778 LADSPA_Data ub = p->PortRangeHints[port].UpperBound;
|
Chris@0
|
779
|
Chris@0
|
780 float value = (float)cv;
|
Chris@0
|
781
|
Chris@0
|
782 if (!LADSPA_IS_HINT_BOUNDED_BELOW(d)) {
|
Chris@0
|
783 if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
|
Chris@0
|
784 /* unbounded: might as well leave the value alone. */
|
Chris@0
|
785 } else {
|
Chris@0
|
786 /* bounded above only. just shift the range. */
|
Chris@0
|
787 value = ub - 127.0f + value;
|
Chris@0
|
788 }
|
Chris@0
|
789 } else {
|
Chris@0
|
790 if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d)) {
|
Chris@0
|
791 /* bounded below only. just shift the range. */
|
Chris@0
|
792 value = lb + value;
|
Chris@0
|
793 } else {
|
Chris@0
|
794 /* bounded both ends. more interesting. */
|
Chris@0
|
795 /* XXX !!! todo: fill in logarithmic, sample rate &c */
|
Chris@0
|
796 value = lb + ((ub - lb) * value / 127.0f);
|
Chris@0
|
797 }
|
Chris@0
|
798 }
|
Chris@0
|
799
|
Chris@0
|
800 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@0
|
801 if (m_controlPortsIn[i].first == port) {
|
Chris@0
|
802 setParameterValue(i, value);
|
Chris@0
|
803 }
|
Chris@0
|
804 }
|
Chris@0
|
805 }
|
Chris@0
|
806
|
Chris@0
|
807 float
|
Martin@62
|
808 DSSIPluginInstance::getControlOutputValue(size_t output) const
|
Chris@60
|
809 {
|
Chris@60
|
810 if (output > m_controlPortsOut.size()) return 0.0;
|
Chris@60
|
811 return (*m_controlPortsOut[output].second);
|
Chris@60
|
812 }
|
Chris@60
|
813
|
Chris@60
|
814 float
|
Chris@0
|
815 DSSIPluginInstance::getParameterValue(unsigned int parameter) const
|
Chris@0
|
816 {
|
Chris@0
|
817 #ifdef DEBUG_DSSI
|
Chris@0
|
818 std::cerr << "DSSIPluginInstance::getParameterValue(" << parameter << ")" << std::endl;
|
Chris@0
|
819 #endif
|
Chris@0
|
820 if (parameter >= m_controlPortsIn.size()) return 0.0;
|
Chris@0
|
821 return (*m_controlPortsIn[parameter].second);
|
Chris@0
|
822 }
|
Chris@0
|
823
|
Chris@0
|
824 float
|
Chris@0
|
825 DSSIPluginInstance::getParameterDefault(unsigned int parameter) const
|
Chris@0
|
826 {
|
Chris@0
|
827 if (parameter >= m_controlPortsIn.size()) return 0.0;
|
Chris@0
|
828
|
Chris@0
|
829 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@0
|
830 if (f) {
|
Chris@0
|
831 return f->getPortDefault(m_descriptor->LADSPA_Plugin,
|
Chris@0
|
832 m_controlPortsIn[parameter].first);
|
Chris@0
|
833 } else {
|
Chris@0
|
834 return 0.0f;
|
Chris@0
|
835 }
|
Chris@0
|
836 }
|
Chris@0
|
837
|
Chris@356
|
838 int
|
Chris@356
|
839 DSSIPluginInstance::getParameterDisplayHint(unsigned int parameter) const
|
Chris@356
|
840 {
|
Chris@356
|
841 if (parameter >= m_controlPortsIn.size()) return 0.0;
|
Chris@356
|
842
|
Chris@356
|
843 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@356
|
844 if (f) {
|
Chris@356
|
845 return f->getPortDisplayHint(m_descriptor->LADSPA_Plugin,
|
Chris@356
|
846 m_controlPortsIn[parameter].first);
|
Chris@356
|
847 } else {
|
Chris@356
|
848 return PortHint::NoHint;
|
Chris@356
|
849 }
|
Chris@356
|
850 }
|
Chris@356
|
851
|
Chris@51
|
852 std::string
|
Chris@51
|
853 DSSIPluginInstance::configure(std::string key,
|
Chris@51
|
854 std::string value)
|
Chris@0
|
855 {
|
Chris@51
|
856 if (!m_descriptor || !m_descriptor->configure) return std::string();
|
Chris@0
|
857
|
Chris@51
|
858 if (key == PluginIdentifier::RESERVED_PROJECT_DIRECTORY_KEY.toStdString()) {
|
Chris@0
|
859 #ifdef DSSI_PROJECT_DIRECTORY_KEY
|
Chris@0
|
860 key = DSSI_PROJECT_DIRECTORY_KEY;
|
Chris@0
|
861 #else
|
Chris@51
|
862 return std::string();
|
Chris@0
|
863 #endif
|
Chris@0
|
864 }
|
Chris@0
|
865
|
Chris@0
|
866
|
Chris@0
|
867 #ifdef DEBUG_DSSI
|
Chris@0
|
868 std::cerr << "DSSIPluginInstance::configure(" << key << "," << value << ")" << std::endl;
|
Chris@0
|
869 #endif
|
Chris@0
|
870
|
Chris@0
|
871 char *message = m_descriptor->configure(m_instanceHandle,
|
Chris@51
|
872 key.c_str(),
|
Chris@51
|
873 value.c_str());
|
Chris@0
|
874
|
Chris@0
|
875 m_programCacheValid = false;
|
Chris@0
|
876
|
Chris@75
|
877 m_configurationData[key] = value;
|
Chris@75
|
878
|
Chris@51
|
879 std::string qm;
|
Chris@0
|
880
|
Chris@0
|
881 // Ignore return values from reserved key configuration calls such
|
Chris@0
|
882 // as project directory
|
Chris@0
|
883 #ifdef DSSI_RESERVED_CONFIGURE_PREFIX
|
Chris@51
|
884 if (QString(key.c_str()).startsWith(DSSI_RESERVED_CONFIGURE_PREFIX)) {
|
Chris@0
|
885 return qm;
|
Chris@0
|
886 }
|
Chris@0
|
887 #endif
|
Chris@0
|
888
|
Chris@0
|
889 if (message) {
|
Chris@0
|
890 if (m_descriptor->LADSPA_Plugin && m_descriptor->LADSPA_Plugin->Label) {
|
Chris@51
|
891 qm = std::string(m_descriptor->LADSPA_Plugin->Label) + ": ";
|
Chris@0
|
892 }
|
Chris@0
|
893 qm = qm + message;
|
Chris@0
|
894 free(message);
|
Chris@83
|
895
|
Chris@84
|
896 std::cerr << "DSSIPluginInstance::configure: warning: configure returned message: \"" << qm << "\"" << std::endl;
|
Chris@0
|
897 }
|
Chris@0
|
898
|
Chris@0
|
899 return qm;
|
Chris@0
|
900 }
|
Chris@0
|
901
|
Chris@0
|
902 void
|
Chris@66
|
903 DSSIPluginInstance::sendEvent(const Vamp::RealTime &eventTime,
|
Chris@0
|
904 const void *e)
|
Chris@0
|
905 {
|
Chris@11
|
906 #ifdef DEBUG_DSSI_PROCESS
|
Chris@11
|
907 std::cerr << "DSSIPluginInstance::sendEvent: last was " << m_lastEventSendTime << " (valid " << m_haveLastEventSendTime << "), this is " << eventTime << std::endl;
|
Chris@11
|
908 #endif
|
Chris@11
|
909
|
Chris@11
|
910 // The process mechanism only works correctly if the events are
|
Chris@11
|
911 // sorted. It's the responsibility of the caller to ensure that:
|
Chris@11
|
912 // we will happily drop events here if we find the timeline going
|
Chris@11
|
913 // backwards.
|
Chris@10
|
914 if (m_haveLastEventSendTime &&
|
Chris@10
|
915 m_lastEventSendTime > eventTime) {
|
Chris@11
|
916 #ifdef DEBUG_DSSI_PROCESS
|
Chris@11
|
917 std::cerr << "... clearing down" << std::endl;
|
Chris@11
|
918 #endif
|
Chris@11
|
919 m_haveLastEventSendTime = false;
|
Chris@10
|
920 clearEvents();
|
Chris@10
|
921 }
|
Chris@10
|
922
|
Chris@0
|
923 snd_seq_event_t *event = (snd_seq_event_t *)e;
|
Chris@0
|
924 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
925 std::cerr << "DSSIPluginInstance::sendEvent at " << eventTime << std::endl;
|
Chris@0
|
926 #endif
|
Chris@0
|
927 snd_seq_event_t ev(*event);
|
Chris@0
|
928
|
Chris@0
|
929 ev.time.time.tv_sec = eventTime.sec;
|
Chris@0
|
930 ev.time.time.tv_nsec = eventTime.nsec;
|
Chris@0
|
931
|
Chris@0
|
932 // DSSI doesn't use MIDI channels, it uses run_multiple_synths instead.
|
Chris@0
|
933 ev.data.note.channel = 0;
|
Chris@0
|
934
|
Chris@0
|
935 m_eventBuffer.write(&ev, 1);
|
Chris@11
|
936
|
Chris@11
|
937 m_lastEventSendTime = eventTime;
|
Chris@11
|
938 m_haveLastEventSendTime = true;
|
Chris@0
|
939 }
|
Chris@0
|
940
|
Chris@10
|
941 void
|
Chris@10
|
942 DSSIPluginInstance::clearEvents()
|
Chris@10
|
943 {
|
Chris@10
|
944 m_haveLastEventSendTime = false;
|
Chris@10
|
945 m_eventBuffer.reset();
|
Chris@10
|
946 }
|
Chris@10
|
947
|
Chris@0
|
948 bool
|
Chris@0
|
949 DSSIPluginInstance::handleController(snd_seq_event_t *ev)
|
Chris@0
|
950 {
|
Chris@0
|
951 int controller = ev->data.control.param;
|
Chris@0
|
952
|
Chris@0
|
953 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
954 std::cerr << "DSSIPluginInstance::handleController " << controller << std::endl;
|
Chris@0
|
955 #endif
|
Chris@0
|
956
|
Chris@0
|
957 if (controller == 0) { // bank select MSB
|
Chris@0
|
958
|
Chris@0
|
959 m_pending.msb = ev->data.control.value;
|
Chris@0
|
960
|
Chris@0
|
961 } else if (controller == 32) { // bank select LSB
|
Chris@0
|
962
|
Chris@0
|
963 m_pending.lsb = ev->data.control.value;
|
Chris@0
|
964
|
Chris@0
|
965 } else if (controller > 0 && controller < 128) {
|
Chris@0
|
966
|
Chris@0
|
967 if (m_controllerMap.find(controller) != m_controllerMap.end()) {
|
Chris@0
|
968 int port = m_controllerMap[controller];
|
Chris@0
|
969 setPortValueFromController(port, ev->data.control.value);
|
Chris@0
|
970 } else {
|
Chris@0
|
971 return true; // pass through to plugin
|
Chris@0
|
972 }
|
Chris@0
|
973 }
|
Chris@0
|
974
|
Chris@0
|
975 return false;
|
Chris@0
|
976 }
|
Chris@0
|
977
|
Chris@0
|
978 void
|
Chris@385
|
979 DSSIPluginInstance::run(const Vamp::RealTime &blockTime, size_t count)
|
Chris@0
|
980 {
|
Chris@0
|
981 static snd_seq_event_t localEventBuffer[EVENT_BUFFER_SIZE];
|
Chris@0
|
982 int evCount = 0;
|
Chris@0
|
983
|
Chris@385
|
984 if (count == 0) count = m_blockSize;
|
Chris@385
|
985
|
Chris@0
|
986 bool needLock = false;
|
Chris@0
|
987 if (m_descriptor->select_program) needLock = true;
|
Chris@0
|
988
|
Chris@0
|
989 if (needLock) {
|
Chris@0
|
990 if (!m_processLock.tryLock()) {
|
Chris@0
|
991 for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
|
Chris@0
|
992 memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
|
Chris@0
|
993 }
|
Chris@0
|
994 return;
|
Chris@0
|
995 }
|
Chris@0
|
996 }
|
Chris@0
|
997
|
Chris@0
|
998 if (m_grouped) {
|
Chris@0
|
999 runGrouped(blockTime);
|
Chris@0
|
1000 goto done;
|
Chris@0
|
1001 }
|
Chris@0
|
1002
|
Chris@0
|
1003 if (!m_descriptor || !m_descriptor->run_synth) {
|
Chris@0
|
1004 m_eventBuffer.skip(m_eventBuffer.getReadSpace());
|
Chris@10
|
1005 m_haveLastEventSendTime = false;
|
Chris@0
|
1006 if (m_descriptor->LADSPA_Plugin->run) {
|
Chris@385
|
1007 m_descriptor->LADSPA_Plugin->run(m_instanceHandle, count);
|
Chris@0
|
1008 } else {
|
Chris@0
|
1009 for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
|
Chris@0
|
1010 memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
|
Chris@0
|
1011 }
|
Chris@0
|
1012 }
|
Chris@0
|
1013 m_run = true;
|
Chris@0
|
1014 if (needLock) m_processLock.unlock();
|
Chris@0
|
1015 return;
|
Chris@0
|
1016 }
|
Chris@0
|
1017
|
Chris@0
|
1018 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1019 std::cerr << "DSSIPluginInstance::run(" << blockTime << ")" << std::endl;
|
Chris@0
|
1020 #endif
|
Chris@0
|
1021
|
Chris@0
|
1022 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1023 if (m_eventBuffer.getReadSpace() > 0) {
|
Chris@0
|
1024 std::cerr << "DSSIPluginInstance::run: event buffer has "
|
Chris@0
|
1025 << m_eventBuffer.getReadSpace() << " event(s) in it" << std::endl;
|
Chris@0
|
1026 }
|
Chris@0
|
1027 #endif
|
Chris@0
|
1028
|
Chris@0
|
1029 while (m_eventBuffer.getReadSpace() > 0) {
|
Chris@0
|
1030
|
Chris@0
|
1031 snd_seq_event_t *ev = localEventBuffer + evCount;
|
Chris@0
|
1032 *ev = m_eventBuffer.peekOne();
|
Chris@0
|
1033 bool accept = true;
|
Chris@0
|
1034
|
Chris@66
|
1035 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
|
Chris@0
|
1036
|
Chris@0
|
1037 int frameOffset = 0;
|
Chris@0
|
1038 if (evTime > blockTime) {
|
Chris@66
|
1039 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
|
Chris@0
|
1040 }
|
Chris@0
|
1041
|
Chris@0
|
1042 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1043 std::cerr << "DSSIPluginInstance::run: evTime " << evTime << ", blockTime " << blockTime << ", frameOffset " << frameOffset
|
Chris@0
|
1044 << ", blockSize " << m_blockSize << std::endl;
|
Chris@0
|
1045 std::cerr << "Type: " << int(ev->type) << ", pitch: " << int(ev->data.note.note) << ", velocity: " << int(ev->data.note.velocity) << std::endl;
|
Chris@0
|
1046 #endif
|
Chris@0
|
1047
|
Chris@385
|
1048 if (frameOffset >= int(count)) break;
|
Chris@10
|
1049 if (frameOffset < 0) {
|
Chris@10
|
1050 frameOffset = 0;
|
Chris@10
|
1051 if (ev->type == SND_SEQ_EVENT_NOTEON) {
|
Chris@10
|
1052 m_eventBuffer.skip(1);
|
Chris@10
|
1053 continue;
|
Chris@10
|
1054 }
|
Chris@10
|
1055 }
|
Chris@0
|
1056
|
Chris@0
|
1057 ev->time.tick = frameOffset;
|
Chris@0
|
1058 m_eventBuffer.skip(1);
|
Chris@0
|
1059
|
Chris@0
|
1060 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
|
Chris@0
|
1061 accept = handleController(ev);
|
Chris@0
|
1062 } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
|
Chris@0
|
1063 m_pending.program = ev->data.control.value;
|
Chris@0
|
1064 accept = false;
|
Chris@0
|
1065 }
|
Chris@0
|
1066
|
Chris@0
|
1067 if (accept) {
|
Chris@0
|
1068 if (++evCount >= EVENT_BUFFER_SIZE) break;
|
Chris@0
|
1069 }
|
Chris@0
|
1070 }
|
Chris@0
|
1071
|
Chris@0
|
1072 if (m_pending.program >= 0 && m_descriptor->select_program) {
|
Chris@0
|
1073
|
Chris@0
|
1074 int program = m_pending.program;
|
Chris@0
|
1075 int bank = m_pending.lsb + 128 * m_pending.msb;
|
Chris@0
|
1076
|
Chris@0
|
1077 #ifdef DEBUG_DSSI
|
Chris@0
|
1078 std::cerr << "DSSIPluginInstance::run: making select_program(" << bank << "," << program << ") call" << std::endl;
|
Chris@0
|
1079 #endif
|
Chris@0
|
1080
|
Chris@0
|
1081 m_pending.lsb = m_pending.msb = m_pending.program = -1;
|
Chris@0
|
1082 m_descriptor->select_program(m_instanceHandle, bank, program);
|
Chris@0
|
1083
|
Chris@0
|
1084 #ifdef DEBUG_DSSI
|
Chris@0
|
1085 std::cerr << "DSSIPluginInstance::run: made select_program(" << bank << "," << program << ") call" << std::endl;
|
Chris@0
|
1086 #endif
|
Chris@0
|
1087 }
|
Chris@0
|
1088
|
Chris@0
|
1089 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1090 std::cerr << "DSSIPluginInstance::run: running with " << evCount << " events"
|
Chris@0
|
1091 << std::endl;
|
Chris@0
|
1092 #endif
|
Chris@0
|
1093
|
Chris@385
|
1094 m_descriptor->run_synth(m_instanceHandle, count,
|
Chris@0
|
1095 localEventBuffer, evCount);
|
Chris@0
|
1096
|
Chris@0
|
1097 #ifdef DEBUG_DSSI_PROCESS
|
Chris@385
|
1098 // for (int i = 0; i < count; ++i) {
|
Chris@0
|
1099 // std::cout << m_outputBuffers[0][i] << " ";
|
Chris@0
|
1100 // if (i % 8 == 0) std::cout << std::endl;
|
Chris@0
|
1101 // }
|
Chris@0
|
1102 #endif
|
Chris@0
|
1103
|
Chris@0
|
1104 done:
|
Chris@0
|
1105 if (needLock) m_processLock.unlock();
|
Chris@0
|
1106
|
Chris@0
|
1107 if (m_audioPortsOut.size() == 0) {
|
Chris@0
|
1108 // copy inputs to outputs
|
Chris@0
|
1109 for (size_t ch = 0; ch < m_idealChannelCount; ++ch) {
|
Chris@0
|
1110 size_t sch = ch % m_audioPortsIn.size();
|
Chris@0
|
1111 for (size_t i = 0; i < m_blockSize; ++i) {
|
Chris@0
|
1112 m_outputBuffers[ch][i] = m_inputBuffers[sch][i];
|
Chris@0
|
1113 }
|
Chris@0
|
1114 }
|
Chris@0
|
1115 } else if (m_idealChannelCount < m_audioPortsOut.size()) {
|
Chris@0
|
1116 if (m_idealChannelCount == 1) {
|
Chris@0
|
1117 // mix down to mono
|
Chris@0
|
1118 for (size_t ch = 1; ch < m_audioPortsOut.size(); ++ch) {
|
Chris@0
|
1119 for (size_t i = 0; i < m_blockSize; ++i) {
|
Chris@0
|
1120 m_outputBuffers[0][i] += m_outputBuffers[ch][i];
|
Chris@0
|
1121 }
|
Chris@0
|
1122 }
|
Chris@0
|
1123 }
|
Chris@0
|
1124 } else if (m_idealChannelCount > m_audioPortsOut.size()) {
|
Chris@0
|
1125 // duplicate
|
Chris@0
|
1126 for (size_t ch = m_audioPortsOut.size(); ch < m_idealChannelCount; ++ch) {
|
Chris@0
|
1127 size_t sch = (ch - m_audioPortsOut.size()) % m_audioPortsOut.size();
|
Chris@0
|
1128 for (size_t i = 0; i < m_blockSize; ++i) {
|
Chris@0
|
1129 m_outputBuffers[ch][i] = m_outputBuffers[sch][i];
|
Chris@0
|
1130 }
|
Chris@0
|
1131 }
|
Chris@0
|
1132 }
|
Chris@0
|
1133
|
Chris@0
|
1134 m_lastRunTime = blockTime;
|
Chris@0
|
1135 m_run = true;
|
Chris@0
|
1136 }
|
Chris@0
|
1137
|
Chris@0
|
1138 void
|
Chris@66
|
1139 DSSIPluginInstance::runGrouped(const Vamp::RealTime &blockTime)
|
Chris@0
|
1140 {
|
Chris@0
|
1141 // If something else in our group has just been called for this
|
Chris@0
|
1142 // block time (but we haven't) then we should just write out the
|
Chris@0
|
1143 // results and return; if we have just been called for this block
|
Chris@0
|
1144 // time or nothing else in the group has been, we should run the
|
Chris@0
|
1145 // whole group.
|
Chris@0
|
1146
|
Chris@0
|
1147 bool needRun = true;
|
Chris@0
|
1148
|
Chris@0
|
1149 PluginSet &s = m_groupMap[m_identifier];
|
Chris@0
|
1150
|
Chris@0
|
1151 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1152 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): this is " << this << "; " << s.size() << " elements in m_groupMap[" << m_identifier << "]" << std::endl;
|
Chris@0
|
1153 #endif
|
Chris@0
|
1154
|
Chris@0
|
1155 if (m_lastRunTime != blockTime) {
|
Chris@0
|
1156 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
|
Chris@0
|
1157 DSSIPluginInstance *instance = *i;
|
Chris@0
|
1158 if (instance != this && instance->m_lastRunTime == blockTime) {
|
Chris@0
|
1159 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1160 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): plugin " << instance << " has already been run" << std::endl;
|
Chris@0
|
1161 #endif
|
Chris@0
|
1162 needRun = false;
|
Chris@0
|
1163 }
|
Chris@0
|
1164 }
|
Chris@0
|
1165 }
|
Chris@0
|
1166
|
Chris@0
|
1167 if (!needRun) {
|
Chris@0
|
1168 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1169 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): already run, returning" << std::endl;
|
Chris@0
|
1170 #endif
|
Chris@0
|
1171 return;
|
Chris@0
|
1172 }
|
Chris@0
|
1173
|
Chris@0
|
1174 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1175 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): I'm the first, running" << std::endl;
|
Chris@0
|
1176 #endif
|
Chris@0
|
1177
|
Chris@0
|
1178 size_t index = 0;
|
Chris@0
|
1179 unsigned long *counts = (unsigned long *)
|
Chris@0
|
1180 alloca(m_groupLocalEventBufferCount * sizeof(unsigned long));
|
Chris@0
|
1181 LADSPA_Handle *instances = (LADSPA_Handle *)
|
Chris@0
|
1182 alloca(m_groupLocalEventBufferCount * sizeof(LADSPA_Handle));
|
Chris@0
|
1183
|
Chris@0
|
1184 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
|
Chris@0
|
1185
|
Chris@0
|
1186 if (index >= m_groupLocalEventBufferCount) break;
|
Chris@0
|
1187
|
Chris@0
|
1188 DSSIPluginInstance *instance = *i;
|
Chris@0
|
1189 counts[index] = 0;
|
Chris@0
|
1190 instances[index] = instance->m_instanceHandle;
|
Chris@0
|
1191
|
Chris@0
|
1192 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1193 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): running " << instance << std::endl;
|
Chris@0
|
1194 #endif
|
Chris@0
|
1195
|
Chris@0
|
1196 if (instance->m_pending.program >= 0 &&
|
Chris@0
|
1197 instance->m_descriptor->select_program) {
|
Chris@0
|
1198 int program = instance->m_pending.program;
|
Chris@0
|
1199 int bank = instance->m_pending.lsb + 128 * instance->m_pending.msb;
|
Chris@0
|
1200 instance->m_pending.lsb = instance->m_pending.msb = instance->m_pending.program = -1;
|
Chris@0
|
1201 instance->m_descriptor->select_program
|
Chris@0
|
1202 (instance->m_instanceHandle, bank, program);
|
Chris@0
|
1203 }
|
Chris@0
|
1204
|
Chris@0
|
1205 while (instance->m_eventBuffer.getReadSpace() > 0) {
|
Chris@0
|
1206
|
Chris@0
|
1207 snd_seq_event_t *ev = m_groupLocalEventBuffers[index] + counts[index];
|
Chris@0
|
1208 *ev = instance->m_eventBuffer.peekOne();
|
Chris@0
|
1209 bool accept = true;
|
Chris@0
|
1210
|
Chris@66
|
1211 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
|
Chris@0
|
1212
|
Chris@0
|
1213 int frameOffset = 0;
|
Chris@0
|
1214 if (evTime > blockTime) {
|
Chris@66
|
1215 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
|
Chris@0
|
1216 }
|
Chris@0
|
1217
|
Chris@0
|
1218 #ifdef DEBUG_DSSI_PROCESS
|
Chris@0
|
1219 std::cerr << "DSSIPluginInstance::runGrouped: evTime " << evTime << ", frameOffset " << frameOffset
|
Chris@0
|
1220 << ", block size " << m_blockSize << std::endl;
|
Chris@0
|
1221 #endif
|
Chris@0
|
1222
|
Chris@0
|
1223 if (frameOffset >= int(m_blockSize)) break;
|
Chris@0
|
1224 if (frameOffset < 0) frameOffset = 0;
|
Chris@0
|
1225
|
Chris@0
|
1226 ev->time.tick = frameOffset;
|
Chris@0
|
1227 instance->m_eventBuffer.skip(1);
|
Chris@0
|
1228
|
Chris@0
|
1229 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
|
Chris@0
|
1230 accept = instance->handleController(ev);
|
Chris@0
|
1231 } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
|
Chris@0
|
1232 instance->m_pending.program = ev->data.control.value;
|
Chris@0
|
1233 accept = false;
|
Chris@0
|
1234 }
|
Chris@0
|
1235
|
Chris@0
|
1236 if (accept) {
|
Chris@0
|
1237 if (++counts[index] >= EVENT_BUFFER_SIZE) break;
|
Chris@0
|
1238 }
|
Chris@0
|
1239 }
|
Chris@0
|
1240
|
Chris@0
|
1241 ++index;
|
Chris@0
|
1242 }
|
Chris@0
|
1243
|
Chris@0
|
1244 m_descriptor->run_multiple_synths(index,
|
Chris@0
|
1245 instances,
|
Chris@0
|
1246 m_blockSize,
|
Chris@0
|
1247 m_groupLocalEventBuffers,
|
Chris@0
|
1248 counts);
|
Chris@0
|
1249 }
|
Chris@0
|
1250
|
Chris@0
|
1251 int
|
Chris@259
|
1252 DSSIPluginInstance::requestMidiSend(LADSPA_Handle /* instance */,
|
Chris@259
|
1253 unsigned char /* ports */,
|
Chris@259
|
1254 unsigned char /* channels */)
|
Chris@0
|
1255 {
|
Chris@0
|
1256 // This is called from a non-RT context (during instantiate)
|
Chris@0
|
1257
|
Chris@0
|
1258 std::cerr << "DSSIPluginInstance::requestMidiSend" << std::endl;
|
Chris@0
|
1259 return 1;
|
Chris@0
|
1260 }
|
Chris@0
|
1261
|
Chris@0
|
1262 void
|
Chris@259
|
1263 DSSIPluginInstance::midiSend(LADSPA_Handle /* instance */,
|
Chris@259
|
1264 snd_seq_event_t * /* events */,
|
Chris@259
|
1265 unsigned long /* eventCount */)
|
Chris@0
|
1266 {
|
Chris@0
|
1267 // This is likely to be called from an RT context
|
Chris@0
|
1268
|
Chris@0
|
1269 std::cerr << "DSSIPluginInstance::midiSend" << std::endl;
|
Chris@0
|
1270 }
|
Chris@0
|
1271
|
Chris@0
|
1272 void
|
Chris@0
|
1273 DSSIPluginInstance::NonRTPluginThread::run()
|
Chris@0
|
1274 {
|
Chris@0
|
1275 while (!m_exiting) {
|
Chris@0
|
1276 m_runFunction(m_handle);
|
Chris@0
|
1277 usleep(100000);
|
Chris@0
|
1278 }
|
Chris@0
|
1279 }
|
Chris@0
|
1280
|
Chris@0
|
1281 int
|
Chris@0
|
1282 DSSIPluginInstance::requestNonRTThread(LADSPA_Handle instance,
|
Chris@0
|
1283 void (*runFunction)(LADSPA_Handle))
|
Chris@0
|
1284 {
|
Chris@0
|
1285 NonRTPluginThread *thread = new NonRTPluginThread(instance, runFunction);
|
Chris@0
|
1286 m_threads[instance].insert(thread);
|
Chris@0
|
1287 thread->start();
|
Chris@0
|
1288 return 0;
|
Chris@0
|
1289 }
|
Chris@0
|
1290
|
Chris@0
|
1291 void
|
Chris@0
|
1292 DSSIPluginInstance::deactivate()
|
Chris@0
|
1293 {
|
Chris@0
|
1294 #ifdef DEBUG_DSSI
|
Chris@0
|
1295 std::cerr << "DSSIPluginInstance::deactivate " << m_identifier << std::endl;
|
Chris@0
|
1296 #endif
|
Chris@0
|
1297 if (!m_descriptor || !m_descriptor->LADSPA_Plugin->deactivate) return;
|
Chris@0
|
1298
|
Chris@0
|
1299 for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
|
Chris@0
|
1300 m_backupControlPortsIn[i] = *m_controlPortsIn[i].second;
|
Chris@0
|
1301 }
|
Chris@0
|
1302
|
Chris@0
|
1303 m_descriptor->LADSPA_Plugin->deactivate(m_instanceHandle);
|
Chris@0
|
1304 #ifdef DEBUG_DSSI
|
Chris@0
|
1305 std::cerr << "DSSIPluginInstance::deactivate " << m_identifier << " done" << std::endl;
|
Chris@0
|
1306 #endif
|
Chris@0
|
1307
|
Chris@0
|
1308 m_bufferScavenger.scavenge();
|
Chris@0
|
1309 }
|
Chris@0
|
1310
|
Chris@0
|
1311 void
|
Chris@0
|
1312 DSSIPluginInstance::cleanup()
|
Chris@0
|
1313 {
|
Chris@0
|
1314 #ifdef DEBUG_DSSI
|
Chris@0
|
1315 std::cerr << "DSSIPluginInstance::cleanup " << m_identifier << std::endl;
|
Chris@0
|
1316 #endif
|
Chris@0
|
1317 if (!m_descriptor) return;
|
Chris@0
|
1318
|
Chris@0
|
1319 if (!m_descriptor->LADSPA_Plugin->cleanup) {
|
Chris@0
|
1320 std::cerr << "Bad plugin: plugin id "
|
Chris@0
|
1321 << m_descriptor->LADSPA_Plugin->UniqueID
|
Chris@0
|
1322 << ":" << m_descriptor->LADSPA_Plugin->Label
|
Chris@0
|
1323 << " has no cleanup method!" << std::endl;
|
Chris@0
|
1324 return;
|
Chris@0
|
1325 }
|
Chris@0
|
1326
|
Chris@0
|
1327 m_descriptor->LADSPA_Plugin->cleanup(m_instanceHandle);
|
Chris@0
|
1328 m_instanceHandle = 0;
|
Chris@0
|
1329 #ifdef DEBUG_DSSI
|
Chris@0
|
1330 std::cerr << "DSSIPluginInstance::cleanup " << m_identifier << " done" << std::endl;
|
Chris@0
|
1331 #endif
|
Chris@0
|
1332 }
|
Chris@0
|
1333
|