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