annotate plugin/DSSIPluginInstance.cpp @ 184:5a916fee6d2d

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