annotate plugin/DSSIPluginInstance.cpp @ 1773:fadd9f8aaa27

This output is too annoying, in the perfectly innocuous case of reading from an aggregate model whose components are different lengths
author Chris Cannam
date Wed, 14 Aug 2019 13:54:23 +0100
parents 70e172e6cc59
children f803d3c33f76
rev   line source
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