comparison plugin/DSSIPluginInstance.cpp @ 0:da6937383da8

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