annotate plugin/DSSIPluginInstance.cpp @ 97:22494cc28c9f

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