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