annotate plugin/DSSIPluginInstance.cpp @ 294:2c1e57ad86e7

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