annotate plugin/DSSIPluginInstance.cpp @ 76:af2725b5d6fe

* Implement harmonic cursor in spectrogram * Implement layer export. This doesn't quite do the right thing for the SV XML layer export yet -- it doesn't include layer display information, so when imported, it only creates an invisible model. Could also do with fixing CSV file import so as to work correctly for note and text layers.
author Chris Cannam
date Mon, 10 Apr 2006 17:22:59 +0000
parents 163f3428bbe0
children b2067aff8cd6
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@0 849 }
Chris@0 850
Chris@0 851 return qm;
Chris@0 852 }
Chris@0 853
Chris@0 854 void
Chris@66 855 DSSIPluginInstance::sendEvent(const Vamp::RealTime &eventTime,
Chris@0 856 const void *e)
Chris@0 857 {
Chris@11 858 #ifdef DEBUG_DSSI_PROCESS
Chris@11 859 std::cerr << "DSSIPluginInstance::sendEvent: last was " << m_lastEventSendTime << " (valid " << m_haveLastEventSendTime << "), this is " << eventTime << std::endl;
Chris@11 860 #endif
Chris@11 861
Chris@11 862 // The process mechanism only works correctly if the events are
Chris@11 863 // sorted. It's the responsibility of the caller to ensure that:
Chris@11 864 // we will happily drop events here if we find the timeline going
Chris@11 865 // backwards.
Chris@10 866 if (m_haveLastEventSendTime &&
Chris@10 867 m_lastEventSendTime > eventTime) {
Chris@11 868 #ifdef DEBUG_DSSI_PROCESS
Chris@11 869 std::cerr << "... clearing down" << std::endl;
Chris@11 870 #endif
Chris@11 871 m_haveLastEventSendTime = false;
Chris@10 872 clearEvents();
Chris@10 873 }
Chris@10 874
Chris@0 875 snd_seq_event_t *event = (snd_seq_event_t *)e;
Chris@0 876 #ifdef DEBUG_DSSI_PROCESS
Chris@0 877 std::cerr << "DSSIPluginInstance::sendEvent at " << eventTime << std::endl;
Chris@0 878 #endif
Chris@0 879 snd_seq_event_t ev(*event);
Chris@0 880
Chris@0 881 ev.time.time.tv_sec = eventTime.sec;
Chris@0 882 ev.time.time.tv_nsec = eventTime.nsec;
Chris@0 883
Chris@0 884 // DSSI doesn't use MIDI channels, it uses run_multiple_synths instead.
Chris@0 885 ev.data.note.channel = 0;
Chris@0 886
Chris@0 887 m_eventBuffer.write(&ev, 1);
Chris@11 888
Chris@11 889 m_lastEventSendTime = eventTime;
Chris@11 890 m_haveLastEventSendTime = true;
Chris@0 891 }
Chris@0 892
Chris@10 893 void
Chris@10 894 DSSIPluginInstance::clearEvents()
Chris@10 895 {
Chris@10 896 m_haveLastEventSendTime = false;
Chris@10 897 m_eventBuffer.reset();
Chris@10 898 }
Chris@10 899
Chris@0 900 bool
Chris@0 901 DSSIPluginInstance::handleController(snd_seq_event_t *ev)
Chris@0 902 {
Chris@0 903 int controller = ev->data.control.param;
Chris@0 904
Chris@0 905 #ifdef DEBUG_DSSI_PROCESS
Chris@0 906 std::cerr << "DSSIPluginInstance::handleController " << controller << std::endl;
Chris@0 907 #endif
Chris@0 908
Chris@0 909 if (controller == 0) { // bank select MSB
Chris@0 910
Chris@0 911 m_pending.msb = ev->data.control.value;
Chris@0 912
Chris@0 913 } else if (controller == 32) { // bank select LSB
Chris@0 914
Chris@0 915 m_pending.lsb = ev->data.control.value;
Chris@0 916
Chris@0 917 } else if (controller > 0 && controller < 128) {
Chris@0 918
Chris@0 919 if (m_controllerMap.find(controller) != m_controllerMap.end()) {
Chris@0 920 int port = m_controllerMap[controller];
Chris@0 921 setPortValueFromController(port, ev->data.control.value);
Chris@0 922 } else {
Chris@0 923 return true; // pass through to plugin
Chris@0 924 }
Chris@0 925 }
Chris@0 926
Chris@0 927 return false;
Chris@0 928 }
Chris@0 929
Chris@0 930 void
Chris@66 931 DSSIPluginInstance::run(const Vamp::RealTime &blockTime)
Chris@0 932 {
Chris@0 933 static snd_seq_event_t localEventBuffer[EVENT_BUFFER_SIZE];
Chris@0 934 int evCount = 0;
Chris@0 935
Chris@0 936 bool needLock = false;
Chris@0 937 if (m_descriptor->select_program) needLock = true;
Chris@0 938
Chris@0 939 if (needLock) {
Chris@0 940 if (!m_processLock.tryLock()) {
Chris@0 941 for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
Chris@0 942 memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
Chris@0 943 }
Chris@0 944 return;
Chris@0 945 }
Chris@0 946 }
Chris@0 947
Chris@0 948 if (m_grouped) {
Chris@0 949 runGrouped(blockTime);
Chris@0 950 goto done;
Chris@0 951 }
Chris@0 952
Chris@0 953 if (!m_descriptor || !m_descriptor->run_synth) {
Chris@0 954 m_eventBuffer.skip(m_eventBuffer.getReadSpace());
Chris@10 955 m_haveLastEventSendTime = false;
Chris@0 956 if (m_descriptor->LADSPA_Plugin->run) {
Chris@0 957 m_descriptor->LADSPA_Plugin->run(m_instanceHandle, m_blockSize);
Chris@0 958 } else {
Chris@0 959 for (size_t ch = 0; ch < m_audioPortsOut.size(); ++ch) {
Chris@0 960 memset(m_outputBuffers[ch], 0, m_blockSize * sizeof(sample_t));
Chris@0 961 }
Chris@0 962 }
Chris@0 963 m_run = true;
Chris@0 964 if (needLock) m_processLock.unlock();
Chris@0 965 return;
Chris@0 966 }
Chris@0 967
Chris@0 968 #ifdef DEBUG_DSSI_PROCESS
Chris@0 969 std::cerr << "DSSIPluginInstance::run(" << blockTime << ")" << std::endl;
Chris@0 970 #endif
Chris@0 971
Chris@0 972 #ifdef DEBUG_DSSI_PROCESS
Chris@0 973 if (m_eventBuffer.getReadSpace() > 0) {
Chris@0 974 std::cerr << "DSSIPluginInstance::run: event buffer has "
Chris@0 975 << m_eventBuffer.getReadSpace() << " event(s) in it" << std::endl;
Chris@0 976 }
Chris@0 977 #endif
Chris@0 978
Chris@0 979 while (m_eventBuffer.getReadSpace() > 0) {
Chris@0 980
Chris@0 981 snd_seq_event_t *ev = localEventBuffer + evCount;
Chris@0 982 *ev = m_eventBuffer.peekOne();
Chris@0 983 bool accept = true;
Chris@0 984
Chris@66 985 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
Chris@0 986
Chris@0 987 int frameOffset = 0;
Chris@0 988 if (evTime > blockTime) {
Chris@66 989 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
Chris@0 990 }
Chris@0 991
Chris@0 992 #ifdef DEBUG_DSSI_PROCESS
Chris@0 993 std::cerr << "DSSIPluginInstance::run: evTime " << evTime << ", blockTime " << blockTime << ", frameOffset " << frameOffset
Chris@0 994 << ", blockSize " << m_blockSize << std::endl;
Chris@0 995 std::cerr << "Type: " << int(ev->type) << ", pitch: " << int(ev->data.note.note) << ", velocity: " << int(ev->data.note.velocity) << std::endl;
Chris@0 996 #endif
Chris@0 997
Chris@0 998 if (frameOffset >= int(m_blockSize)) break;
Chris@10 999 if (frameOffset < 0) {
Chris@10 1000 frameOffset = 0;
Chris@10 1001 if (ev->type == SND_SEQ_EVENT_NOTEON) {
Chris@10 1002 m_eventBuffer.skip(1);
Chris@10 1003 continue;
Chris@10 1004 }
Chris@10 1005 }
Chris@0 1006
Chris@0 1007 ev->time.tick = frameOffset;
Chris@0 1008 m_eventBuffer.skip(1);
Chris@0 1009
Chris@0 1010 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
Chris@0 1011 accept = handleController(ev);
Chris@0 1012 } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
Chris@0 1013 m_pending.program = ev->data.control.value;
Chris@0 1014 accept = false;
Chris@0 1015 }
Chris@0 1016
Chris@0 1017 if (accept) {
Chris@0 1018 if (++evCount >= EVENT_BUFFER_SIZE) break;
Chris@0 1019 }
Chris@0 1020 }
Chris@0 1021
Chris@0 1022 if (m_pending.program >= 0 && m_descriptor->select_program) {
Chris@0 1023
Chris@0 1024 int program = m_pending.program;
Chris@0 1025 int bank = m_pending.lsb + 128 * m_pending.msb;
Chris@0 1026
Chris@0 1027 #ifdef DEBUG_DSSI
Chris@0 1028 std::cerr << "DSSIPluginInstance::run: making select_program(" << bank << "," << program << ") call" << std::endl;
Chris@0 1029 #endif
Chris@0 1030
Chris@0 1031 m_pending.lsb = m_pending.msb = m_pending.program = -1;
Chris@0 1032 m_descriptor->select_program(m_instanceHandle, bank, program);
Chris@0 1033
Chris@0 1034 #ifdef DEBUG_DSSI
Chris@0 1035 std::cerr << "DSSIPluginInstance::run: made select_program(" << bank << "," << program << ") call" << std::endl;
Chris@0 1036 #endif
Chris@0 1037 }
Chris@0 1038
Chris@0 1039 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1040 std::cerr << "DSSIPluginInstance::run: running with " << evCount << " events"
Chris@0 1041 << std::endl;
Chris@0 1042 #endif
Chris@0 1043
Chris@0 1044 m_descriptor->run_synth(m_instanceHandle, m_blockSize,
Chris@0 1045 localEventBuffer, evCount);
Chris@0 1046
Chris@0 1047 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1048 // for (int i = 0; i < m_blockSize; ++i) {
Chris@0 1049 // std::cout << m_outputBuffers[0][i] << " ";
Chris@0 1050 // if (i % 8 == 0) std::cout << std::endl;
Chris@0 1051 // }
Chris@0 1052 #endif
Chris@0 1053
Chris@0 1054 done:
Chris@0 1055 if (needLock) m_processLock.unlock();
Chris@0 1056
Chris@0 1057 if (m_audioPortsOut.size() == 0) {
Chris@0 1058 // copy inputs to outputs
Chris@0 1059 for (size_t ch = 0; ch < m_idealChannelCount; ++ch) {
Chris@0 1060 size_t sch = ch % m_audioPortsIn.size();
Chris@0 1061 for (size_t i = 0; i < m_blockSize; ++i) {
Chris@0 1062 m_outputBuffers[ch][i] = m_inputBuffers[sch][i];
Chris@0 1063 }
Chris@0 1064 }
Chris@0 1065 } else if (m_idealChannelCount < m_audioPortsOut.size()) {
Chris@0 1066 if (m_idealChannelCount == 1) {
Chris@0 1067 // mix down to mono
Chris@0 1068 for (size_t ch = 1; ch < m_audioPortsOut.size(); ++ch) {
Chris@0 1069 for (size_t i = 0; i < m_blockSize; ++i) {
Chris@0 1070 m_outputBuffers[0][i] += m_outputBuffers[ch][i];
Chris@0 1071 }
Chris@0 1072 }
Chris@0 1073 }
Chris@0 1074 } else if (m_idealChannelCount > m_audioPortsOut.size()) {
Chris@0 1075 // duplicate
Chris@0 1076 for (size_t ch = m_audioPortsOut.size(); ch < m_idealChannelCount; ++ch) {
Chris@0 1077 size_t sch = (ch - m_audioPortsOut.size()) % m_audioPortsOut.size();
Chris@0 1078 for (size_t i = 0; i < m_blockSize; ++i) {
Chris@0 1079 m_outputBuffers[ch][i] = m_outputBuffers[sch][i];
Chris@0 1080 }
Chris@0 1081 }
Chris@0 1082 }
Chris@0 1083
Chris@0 1084 m_lastRunTime = blockTime;
Chris@0 1085 m_run = true;
Chris@0 1086 }
Chris@0 1087
Chris@0 1088 void
Chris@66 1089 DSSIPluginInstance::runGrouped(const Vamp::RealTime &blockTime)
Chris@0 1090 {
Chris@0 1091 // If something else in our group has just been called for this
Chris@0 1092 // block time (but we haven't) then we should just write out the
Chris@0 1093 // results and return; if we have just been called for this block
Chris@0 1094 // time or nothing else in the group has been, we should run the
Chris@0 1095 // whole group.
Chris@0 1096
Chris@0 1097 bool needRun = true;
Chris@0 1098
Chris@0 1099 PluginSet &s = m_groupMap[m_identifier];
Chris@0 1100
Chris@0 1101 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1102 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): this is " << this << "; " << s.size() << " elements in m_groupMap[" << m_identifier << "]" << std::endl;
Chris@0 1103 #endif
Chris@0 1104
Chris@0 1105 if (m_lastRunTime != blockTime) {
Chris@0 1106 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
Chris@0 1107 DSSIPluginInstance *instance = *i;
Chris@0 1108 if (instance != this && instance->m_lastRunTime == blockTime) {
Chris@0 1109 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1110 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): plugin " << instance << " has already been run" << std::endl;
Chris@0 1111 #endif
Chris@0 1112 needRun = false;
Chris@0 1113 }
Chris@0 1114 }
Chris@0 1115 }
Chris@0 1116
Chris@0 1117 if (!needRun) {
Chris@0 1118 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1119 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): already run, returning" << std::endl;
Chris@0 1120 #endif
Chris@0 1121 return;
Chris@0 1122 }
Chris@0 1123
Chris@0 1124 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1125 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): I'm the first, running" << std::endl;
Chris@0 1126 #endif
Chris@0 1127
Chris@0 1128 size_t index = 0;
Chris@0 1129 unsigned long *counts = (unsigned long *)
Chris@0 1130 alloca(m_groupLocalEventBufferCount * sizeof(unsigned long));
Chris@0 1131 LADSPA_Handle *instances = (LADSPA_Handle *)
Chris@0 1132 alloca(m_groupLocalEventBufferCount * sizeof(LADSPA_Handle));
Chris@0 1133
Chris@0 1134 for (PluginSet::iterator i = s.begin(); i != s.end(); ++i) {
Chris@0 1135
Chris@0 1136 if (index >= m_groupLocalEventBufferCount) break;
Chris@0 1137
Chris@0 1138 DSSIPluginInstance *instance = *i;
Chris@0 1139 counts[index] = 0;
Chris@0 1140 instances[index] = instance->m_instanceHandle;
Chris@0 1141
Chris@0 1142 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1143 std::cerr << "DSSIPluginInstance::runGrouped(" << blockTime << "): running " << instance << std::endl;
Chris@0 1144 #endif
Chris@0 1145
Chris@0 1146 if (instance->m_pending.program >= 0 &&
Chris@0 1147 instance->m_descriptor->select_program) {
Chris@0 1148 int program = instance->m_pending.program;
Chris@0 1149 int bank = instance->m_pending.lsb + 128 * instance->m_pending.msb;
Chris@0 1150 instance->m_pending.lsb = instance->m_pending.msb = instance->m_pending.program = -1;
Chris@0 1151 instance->m_descriptor->select_program
Chris@0 1152 (instance->m_instanceHandle, bank, program);
Chris@0 1153 }
Chris@0 1154
Chris@0 1155 while (instance->m_eventBuffer.getReadSpace() > 0) {
Chris@0 1156
Chris@0 1157 snd_seq_event_t *ev = m_groupLocalEventBuffers[index] + counts[index];
Chris@0 1158 *ev = instance->m_eventBuffer.peekOne();
Chris@0 1159 bool accept = true;
Chris@0 1160
Chris@66 1161 Vamp::RealTime evTime(ev->time.time.tv_sec, ev->time.time.tv_nsec);
Chris@0 1162
Chris@0 1163 int frameOffset = 0;
Chris@0 1164 if (evTime > blockTime) {
Chris@66 1165 frameOffset = Vamp::RealTime::realTime2Frame(evTime - blockTime, m_sampleRate);
Chris@0 1166 }
Chris@0 1167
Chris@0 1168 #ifdef DEBUG_DSSI_PROCESS
Chris@0 1169 std::cerr << "DSSIPluginInstance::runGrouped: evTime " << evTime << ", frameOffset " << frameOffset
Chris@0 1170 << ", block size " << m_blockSize << std::endl;
Chris@0 1171 #endif
Chris@0 1172
Chris@0 1173 if (frameOffset >= int(m_blockSize)) break;
Chris@0 1174 if (frameOffset < 0) frameOffset = 0;
Chris@0 1175
Chris@0 1176 ev->time.tick = frameOffset;
Chris@0 1177 instance->m_eventBuffer.skip(1);
Chris@0 1178
Chris@0 1179 if (ev->type == SND_SEQ_EVENT_CONTROLLER) {
Chris@0 1180 accept = instance->handleController(ev);
Chris@0 1181 } else if (ev->type == SND_SEQ_EVENT_PGMCHANGE) {
Chris@0 1182 instance->m_pending.program = ev->data.control.value;
Chris@0 1183 accept = false;
Chris@0 1184 }
Chris@0 1185
Chris@0 1186 if (accept) {
Chris@0 1187 if (++counts[index] >= EVENT_BUFFER_SIZE) break;
Chris@0 1188 }
Chris@0 1189 }
Chris@0 1190
Chris@0 1191 ++index;
Chris@0 1192 }
Chris@0 1193
Chris@0 1194 m_descriptor->run_multiple_synths(index,
Chris@0 1195 instances,
Chris@0 1196 m_blockSize,
Chris@0 1197 m_groupLocalEventBuffers,
Chris@0 1198 counts);
Chris@0 1199 }
Chris@0 1200
Chris@0 1201 int
Chris@0 1202 DSSIPluginInstance::requestMidiSend(LADSPA_Handle instance,
Chris@0 1203 unsigned char ports,
Chris@0 1204 unsigned char channels)
Chris@0 1205 {
Chris@0 1206 // This is called from a non-RT context (during instantiate)
Chris@0 1207
Chris@0 1208 std::cerr << "DSSIPluginInstance::requestMidiSend" << std::endl;
Chris@0 1209 return 1;
Chris@0 1210 }
Chris@0 1211
Chris@0 1212 void
Chris@0 1213 DSSIPluginInstance::midiSend(LADSPA_Handle instance,
Chris@0 1214 snd_seq_event_t *events,
Chris@0 1215 unsigned long eventCount)
Chris@0 1216 {
Chris@0 1217 // This is likely to be called from an RT context
Chris@0 1218
Chris@0 1219 std::cerr << "DSSIPluginInstance::midiSend" << std::endl;
Chris@0 1220 }
Chris@0 1221
Chris@0 1222 void
Chris@0 1223 DSSIPluginInstance::NonRTPluginThread::run()
Chris@0 1224 {
Chris@0 1225 while (!m_exiting) {
Chris@0 1226 m_runFunction(m_handle);
Chris@0 1227 usleep(100000);
Chris@0 1228 }
Chris@0 1229 }
Chris@0 1230
Chris@0 1231 int
Chris@0 1232 DSSIPluginInstance::requestNonRTThread(LADSPA_Handle instance,
Chris@0 1233 void (*runFunction)(LADSPA_Handle))
Chris@0 1234 {
Chris@0 1235 NonRTPluginThread *thread = new NonRTPluginThread(instance, runFunction);
Chris@0 1236 m_threads[instance].insert(thread);
Chris@0 1237 thread->start();
Chris@0 1238 return 0;
Chris@0 1239 }
Chris@0 1240
Chris@0 1241 void
Chris@0 1242 DSSIPluginInstance::deactivate()
Chris@0 1243 {
Chris@0 1244 #ifdef DEBUG_DSSI
Chris@0 1245 std::cerr << "DSSIPluginInstance::deactivate " << m_identifier << std::endl;
Chris@0 1246 #endif
Chris@0 1247 if (!m_descriptor || !m_descriptor->LADSPA_Plugin->deactivate) return;
Chris@0 1248
Chris@0 1249 for (size_t i = 0; i < m_backupControlPortsIn.size(); ++i) {
Chris@0 1250 m_backupControlPortsIn[i] = *m_controlPortsIn[i].second;
Chris@0 1251 }
Chris@0 1252
Chris@0 1253 m_descriptor->LADSPA_Plugin->deactivate(m_instanceHandle);
Chris@0 1254 #ifdef DEBUG_DSSI
Chris@0 1255 std::cerr << "DSSIPluginInstance::deactivate " << m_identifier << " done" << std::endl;
Chris@0 1256 #endif
Chris@0 1257
Chris@0 1258 m_bufferScavenger.scavenge();
Chris@0 1259 }
Chris@0 1260
Chris@0 1261 void
Chris@0 1262 DSSIPluginInstance::cleanup()
Chris@0 1263 {
Chris@0 1264 #ifdef DEBUG_DSSI
Chris@0 1265 std::cerr << "DSSIPluginInstance::cleanup " << m_identifier << std::endl;
Chris@0 1266 #endif
Chris@0 1267 if (!m_descriptor) return;
Chris@0 1268
Chris@0 1269 if (!m_descriptor->LADSPA_Plugin->cleanup) {
Chris@0 1270 std::cerr << "Bad plugin: plugin id "
Chris@0 1271 << m_descriptor->LADSPA_Plugin->UniqueID
Chris@0 1272 << ":" << m_descriptor->LADSPA_Plugin->Label
Chris@0 1273 << " has no cleanup method!" << std::endl;
Chris@0 1274 return;
Chris@0 1275 }
Chris@0 1276
Chris@0 1277 m_descriptor->LADSPA_Plugin->cleanup(m_instanceHandle);
Chris@0 1278 m_instanceHandle = 0;
Chris@0 1279 #ifdef DEBUG_DSSI
Chris@0 1280 std::cerr << "DSSIPluginInstance::cleanup " << m_identifier << " done" << std::endl;
Chris@0 1281 #endif
Chris@0 1282 }
Chris@0 1283