annotate plugin/LADSPAPluginInstance.cpp @ 167:665342c6ec57

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +0000
parents 702fc936e6a6
children 570794f6f6a7
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 and Richard Bown.
Chris@0 19 */
Chris@0 20
Chris@0 21 #include <iostream>
Chris@0 22 #include <cassert>
Chris@0 23
Chris@0 24 #include "LADSPAPluginInstance.h"
Chris@0 25 #include "LADSPAPluginFactory.h"
Chris@0 26
Chris@166 27 #ifdef HAVE_LRDF
Chris@166 28 #include "lrdf.h"
Chris@166 29 #endif // HAVE_LRDF
Chris@166 30
Chris@117 31 //#define DEBUG_LADSPA 1
Chris@0 32
Chris@0 33
Chris@0 34 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory,
Chris@0 35 int clientId,
Chris@0 36 QString identifier,
Chris@0 37 int position,
Chris@0 38 unsigned long sampleRate,
Chris@0 39 size_t blockSize,
Chris@0 40 int idealChannelCount,
Chris@0 41 const LADSPA_Descriptor* descriptor) :
Chris@0 42 RealTimePluginInstance(factory, identifier),
Chris@0 43 m_client(clientId),
Chris@0 44 m_position(position),
Chris@0 45 m_instanceCount(0),
Chris@0 46 m_descriptor(descriptor),
Chris@0 47 m_blockSize(blockSize),
Chris@0 48 m_sampleRate(sampleRate),
Chris@0 49 m_latencyPort(0),
Chris@0 50 m_run(false),
Chris@0 51 m_bypassed(false)
Chris@0 52 {
Chris@0 53 init(idealChannelCount);
Chris@0 54
Chris@0 55 m_inputBuffers = new sample_t*[m_instanceCount * m_audioPortsIn.size()];
Chris@0 56 m_outputBuffers = new sample_t*[m_instanceCount * m_audioPortsOut.size()];
Chris@0 57
Chris@0 58 for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) {
Chris@0 59 m_inputBuffers[i] = new sample_t[blockSize];
Chris@0 60 }
Chris@0 61 for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) {
Chris@0 62 m_outputBuffers[i] = new sample_t[blockSize];
Chris@0 63 }
Chris@0 64
Chris@0 65 m_ownBuffers = true;
Chris@0 66
Chris@0 67 instantiate(sampleRate);
Chris@0 68 if (isOK()) {
Chris@0 69 connectPorts();
Chris@0 70 activate();
Chris@0 71 }
Chris@0 72 }
Chris@0 73
Chris@51 74 std::string
Chris@51 75 LADSPAPluginInstance::getName() const
Chris@0 76 {
Chris@51 77 return m_descriptor->Label;
Chris@0 78 }
Chris@0 79
Chris@51 80 std::string
Chris@51 81 LADSPAPluginInstance::getDescription() const
Chris@51 82 {
Chris@51 83 return m_descriptor->Name;
Chris@51 84 }
Chris@51 85
Chris@51 86 std::string
Chris@51 87 LADSPAPluginInstance::getMaker() const
Chris@51 88 {
Chris@51 89 return m_descriptor->Maker;
Chris@51 90 }
Chris@51 91
Chris@51 92 int
Chris@51 93 LADSPAPluginInstance::getPluginVersion() const
Chris@51 94 {
Chris@51 95 return 1;
Chris@51 96 }
Chris@51 97
Chris@51 98 std::string
Chris@51 99 LADSPAPluginInstance::getCopyright() const
Chris@51 100 {
Chris@51 101 return m_descriptor->Copyright;
Chris@51 102 }
Chris@51 103
Chris@51 104 LADSPAPluginInstance::ParameterList
Chris@51 105 LADSPAPluginInstance::getParameterDescriptors() const
Chris@51 106 {
Chris@51 107 ParameterList list;
Chris@51 108 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@51 109
Chris@51 110 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 111
Chris@51 112 ParameterDescriptor pd;
Chris@51 113 unsigned int pn = m_controlPortsIn[i].first;
Chris@51 114
Chris@51 115 pd.name = m_descriptor->PortNames[pn];
Chris@51 116 pd.description = pd.name;
Chris@51 117 pd.minValue = f->getPortMinimum(m_descriptor, pn);
Chris@51 118 pd.maxValue = f->getPortMaximum(m_descriptor, pn);
Chris@51 119 pd.defaultValue = f->getPortDefault(m_descriptor, pn);
Chris@57 120
Chris@57 121 float q = f->getPortQuantization(m_descriptor, pn);
Chris@57 122 if (q == 0.0) {
Chris@57 123 pd.isQuantized = false;
Chris@57 124 } else {
Chris@57 125 pd.isQuantized = true;
Chris@57 126 pd.quantizeStep = q;
Chris@57 127 }
Chris@51 128
Chris@166 129 bool haveLabels = false;
Chris@166 130
Chris@166 131 #ifdef HAVE_LRDF
Chris@166 132 if (pd.isQuantized && pd.quantizeStep == 1.0) {
Chris@166 133
Chris@166 134 lrdf_defaults *defaults =
Chris@166 135 lrdf_get_scale_values(m_descriptor->UniqueID, pn);
Chris@166 136
Chris@166 137 if (defaults) {
Chris@166 138 if (defaults->count > 0) {
Chris@166 139 std::map<int, std::string> values;
Chris@166 140 int v = 0;
Chris@166 141 for (size_t i = 0; i < defaults->count; ++i) {
Chris@166 142 v = defaults->items[i].value;
Chris@166 143 values[v] = defaults->items[i].label;
Chris@166 144 }
Chris@166 145 for (size_t i = 0; i <= v; ++i) {
Chris@166 146 pd.valueNames.push_back(values[i]);
Chris@166 147 }
Chris@166 148 haveLabels = true;
Chris@166 149 }
Chris@166 150 lrdf_free_setting_values(defaults);
Chris@166 151 }
Chris@166 152 }
Chris@166 153 #endif
Chris@166 154
Chris@166 155 if (haveLabels) {
Chris@166 156 pd.description = QString(pd.description.c_str())
Chris@166 157 .replace(QRegExp("\\([^\\(\\)]+=[^\\(\\)]+\\)$"), "")
Chris@166 158 .toStdString();
Chris@166 159 } else {
Chris@166 160 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
Chris@166 161 if (unitRE.indexIn(pd.name.c_str()) >= 0) {
Chris@166 162 pd.unit = unitRE.cap(1).toStdString();
Chris@166 163 pd.description = QString(pd.description.c_str())
Chris@166 164 .replace(unitRE, "").toStdString();
Chris@166 165 }
Chris@166 166 }
Chris@166 167
Chris@51 168 list.push_back(pd);
Chris@51 169 }
Chris@51 170
Chris@51 171 return list;
Chris@51 172 }
Chris@51 173
Chris@51 174 float
Chris@51 175 LADSPAPluginInstance::getParameter(std::string name) const
Chris@51 176 {
Chris@51 177 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 178 if (name == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
Chris@51 179 return getParameterValue(i);
Chris@51 180 }
Chris@51 181 }
Chris@51 182
Chris@51 183 return 0.0;
Chris@51 184 }
Chris@51 185
Chris@51 186 void
Chris@51 187 LADSPAPluginInstance::setParameter(std::string name, float value)
Chris@51 188 {
Chris@51 189 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 190 if (name == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
Chris@51 191 setParameterValue(i, value);
Chris@51 192 break;
Chris@51 193 }
Chris@51 194 }
Chris@51 195 }
Chris@0 196
Chris@0 197 void
Chris@0 198 LADSPAPluginInstance::init(int idealChannelCount)
Chris@0 199 {
Chris@0 200 #ifdef DEBUG_LADSPA
Chris@0 201 std::cerr << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has "
Chris@0 202 << m_descriptor->PortCount << " ports" << std::endl;
Chris@0 203 #endif
Chris@0 204
Chris@0 205 // Discover ports numbers and identities
Chris@0 206 //
Chris@0 207 for (unsigned long i = 0; i < m_descriptor->PortCount; ++i)
Chris@0 208 {
Chris@0 209 if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i]))
Chris@0 210 {
Chris@0 211 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
Chris@0 212 #ifdef DEBUG_LADSPA
Chris@0 213 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio in" << std::endl;
Chris@0 214 #endif
Chris@0 215 m_audioPortsIn.push_back(i);
Chris@0 216 } else {
Chris@0 217 #ifdef DEBUG_LADSPA
Chris@0 218 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio out" << std::endl;
Chris@0 219 #endif
Chris@0 220 m_audioPortsOut.push_back(i);
Chris@0 221 }
Chris@0 222 }
Chris@0 223 else
Chris@0 224 if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i]))
Chris@0 225 {
Chris@0 226 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
Chris@0 227 #ifdef DEBUG_LADSPA
Chris@0 228 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control in" << std::endl;
Chris@0 229 #endif
Chris@0 230 LADSPA_Data *data = new LADSPA_Data(0.0);
Chris@0 231 m_controlPortsIn.push_back(
Chris@0 232 std::pair<unsigned long, LADSPA_Data*>(i, data));
Chris@0 233 } else {
Chris@0 234 #ifdef DEBUG_LADSPA
Chris@0 235 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control out" << std::endl;
Chris@0 236 #endif
Chris@0 237 LADSPA_Data *data = new LADSPA_Data(0.0);
Chris@0 238 m_controlPortsOut.push_back(
Chris@0 239 std::pair<unsigned long, LADSPA_Data*>(i, data));
Chris@0 240 if (!strcmp(m_descriptor->PortNames[i], "latency") ||
Chris@0 241 !strcmp(m_descriptor->PortNames[i], "_latency")) {
Chris@0 242 #ifdef DEBUG_LADSPA
Chris@0 243 std::cerr << "Wooo! We have a latency port!" << std::endl;
Chris@0 244 #endif
Chris@0 245 m_latencyPort = data;
Chris@0 246 }
Chris@0 247 }
Chris@0 248 }
Chris@0 249 #ifdef DEBUG_LADSPA
Chris@0 250 else
Chris@0 251 std::cerr << "LADSPAPluginInstance::init - "
Chris@0 252 << "unrecognised port type" << std::endl;
Chris@0 253 #endif
Chris@0 254 }
Chris@0 255
Chris@0 256 m_instanceCount = 1;
Chris@0 257
Chris@0 258 if (idealChannelCount > 0) {
Chris@0 259 if (m_audioPortsIn.size() == 1) {
Chris@0 260 // mono plugin: duplicate it if need be
Chris@0 261 m_instanceCount = idealChannelCount;
Chris@0 262 }
Chris@0 263 }
Chris@0 264 }
Chris@0 265
Chris@0 266 size_t
Chris@0 267 LADSPAPluginInstance::getLatency()
Chris@0 268 {
Chris@0 269 if (m_latencyPort) {
Chris@66 270 if (!m_run) run(Vamp::RealTime::zeroTime);
Chris@0 271 if (*m_latencyPort > 0) return (size_t)*m_latencyPort;
Chris@0 272 }
Chris@0 273 return 0;
Chris@0 274 }
Chris@0 275
Chris@0 276 void
Chris@0 277 LADSPAPluginInstance::silence()
Chris@0 278 {
Chris@0 279 if (isOK()) {
Chris@0 280 deactivate();
Chris@0 281 activate();
Chris@0 282 }
Chris@0 283 }
Chris@0 284
Chris@0 285 void
Chris@0 286 LADSPAPluginInstance::setIdealChannelCount(size_t channels)
Chris@0 287 {
Chris@0 288 if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) {
Chris@0 289 silence();
Chris@0 290 return;
Chris@0 291 }
Chris@0 292
Chris@0 293 if (isOK()) {
Chris@0 294 deactivate();
Chris@0 295 }
Chris@0 296
Chris@0 297 //!!! don't we need to reallocate inputBuffers and outputBuffers?
Chris@0 298
Chris@0 299 cleanup();
Chris@0 300 m_instanceCount = channels;
Chris@0 301 instantiate(m_sampleRate);
Chris@0 302 if (isOK()) {
Chris@0 303 connectPorts();
Chris@0 304 activate();
Chris@0 305 }
Chris@0 306 }
Chris@0 307
Chris@0 308
Chris@0 309 LADSPAPluginInstance::~LADSPAPluginInstance()
Chris@0 310 {
Chris@0 311 #ifdef DEBUG_LADSPA
Chris@0 312 std::cerr << "LADSPAPluginInstance::~LADSPAPluginInstance" << std::endl;
Chris@0 313 #endif
Chris@0 314
Chris@0 315 if (m_instanceHandles.size() != 0) { // "isOK()"
Chris@0 316 deactivate();
Chris@0 317 }
Chris@0 318
Chris@0 319 cleanup();
Chris@0 320
Chris@0 321 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i)
Chris@0 322 delete m_controlPortsIn[i].second;
Chris@0 323
Chris@0 324 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i)
Chris@0 325 delete m_controlPortsOut[i].second;
Chris@0 326
Chris@0 327 m_controlPortsIn.clear();
Chris@0 328 m_controlPortsOut.clear();
Chris@0 329
Chris@0 330 if (m_ownBuffers) {
Chris@0 331 for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
Chris@0 332 delete[] m_inputBuffers[i];
Chris@0 333 }
Chris@0 334 for (size_t i = 0; i < m_audioPortsOut.size(); ++i) {
Chris@0 335 delete[] m_outputBuffers[i];
Chris@0 336 }
Chris@0 337
Chris@0 338 delete[] m_inputBuffers;
Chris@0 339 delete[] m_outputBuffers;
Chris@0 340 }
Chris@0 341
Chris@0 342 m_audioPortsIn.clear();
Chris@0 343 m_audioPortsOut.clear();
Chris@0 344 }
Chris@0 345
Chris@0 346
Chris@0 347 void
Chris@0 348 LADSPAPluginInstance::instantiate(unsigned long sampleRate)
Chris@0 349 {
Chris@0 350 #ifdef DEBUG_LADSPA
Chris@0 351 std::cout << "LADSPAPluginInstance::instantiate - plugin unique id = "
Chris@0 352 << m_descriptor->UniqueID << std::endl;
Chris@0 353 #endif
Chris@0 354 if (!m_descriptor) return;
Chris@0 355
Chris@0 356 if (!m_descriptor->instantiate) {
Chris@0 357 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
Chris@0 358 << ":" << m_descriptor->Label
Chris@0 359 << " has no instantiate method!" << std::endl;
Chris@0 360 return;
Chris@0 361 }
Chris@0 362
Chris@0 363 for (size_t i = 0; i < m_instanceCount; ++i) {
Chris@0 364 m_instanceHandles.push_back
Chris@0 365 (m_descriptor->instantiate(m_descriptor, sampleRate));
Chris@0 366 }
Chris@0 367 }
Chris@0 368
Chris@0 369 void
Chris@0 370 LADSPAPluginInstance::activate()
Chris@0 371 {
Chris@0 372 if (!m_descriptor || !m_descriptor->activate) return;
Chris@0 373
Chris@0 374 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 375 hi != m_instanceHandles.end(); ++hi) {
Chris@0 376 m_descriptor->activate(*hi);
Chris@0 377 }
Chris@0 378 }
Chris@0 379
Chris@0 380 void
Chris@0 381 LADSPAPluginInstance::connectPorts()
Chris@0 382 {
Chris@0 383 if (!m_descriptor || !m_descriptor->connect_port) return;
Chris@0 384
Chris@0 385 assert(sizeof(LADSPA_Data) == sizeof(float));
Chris@0 386 assert(sizeof(sample_t) == sizeof(float));
Chris@0 387
Chris@57 388 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 389 int inbuf = 0, outbuf = 0;
Chris@0 390
Chris@0 391 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 392 hi != m_instanceHandles.end(); ++hi) {
Chris@0 393
Chris@0 394 for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) {
Chris@0 395 m_descriptor->connect_port(*hi,
Chris@0 396 m_audioPortsIn[i],
Chris@0 397 (LADSPA_Data *)m_inputBuffers[inbuf]);
Chris@0 398 ++inbuf;
Chris@0 399 }
Chris@0 400
Chris@0 401 for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) {
Chris@0 402 m_descriptor->connect_port(*hi,
Chris@0 403 m_audioPortsOut[i],
Chris@0 404 (LADSPA_Data *)m_outputBuffers[outbuf]);
Chris@0 405 ++outbuf;
Chris@0 406 }
Chris@0 407
Chris@0 408 // If there is more than one instance, they all share the same
Chris@0 409 // control port ins (and outs, for the moment, because we
Chris@0 410 // don't actually do anything with the outs anyway -- but they
Chris@0 411 // do have to be connected as the plugin can't know if they're
Chris@0 412 // not and will write to them anyway).
Chris@0 413
Chris@0 414 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@0 415 m_descriptor->connect_port(*hi,
Chris@0 416 m_controlPortsIn[i].first,
Chris@0 417 m_controlPortsIn[i].second);
Chris@57 418 if (f) {
Chris@57 419 float defaultValue = f->getPortDefault
Chris@57 420 (m_descriptor, m_controlPortsIn[i].first);
Chris@57 421 *m_controlPortsIn[i].second = defaultValue;
Chris@57 422 }
Chris@0 423 }
Chris@0 424
Chris@0 425 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) {
Chris@0 426 m_descriptor->connect_port(*hi,
Chris@0 427 m_controlPortsOut[i].first,
Chris@0 428 m_controlPortsOut[i].second);
Chris@0 429 }
Chris@0 430 }
Chris@0 431 }
Chris@0 432
Chris@0 433 unsigned int
Chris@0 434 LADSPAPluginInstance::getParameterCount() const
Chris@0 435 {
Chris@0 436 return m_controlPortsIn.size();
Chris@0 437 }
Chris@0 438
Chris@0 439 void
Chris@0 440 LADSPAPluginInstance::setParameterValue(unsigned int parameter, float value)
Chris@0 441 {
Chris@0 442 if (parameter >= m_controlPortsIn.size()) return;
Chris@0 443
Chris@0 444 unsigned int portNumber = m_controlPortsIn[parameter].first;
Chris@0 445
Chris@0 446 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 447 if (f) {
Chris@0 448 if (value < f->getPortMinimum(m_descriptor, portNumber)) {
Chris@0 449 value = f->getPortMinimum(m_descriptor, portNumber);
Chris@0 450 }
Chris@0 451 if (value > f->getPortMaximum(m_descriptor, portNumber)) {
Chris@0 452 value = f->getPortMaximum(m_descriptor, portNumber);
Chris@0 453 }
Chris@0 454 }
Chris@0 455
Chris@0 456 (*m_controlPortsIn[parameter].second) = value;
Chris@0 457 }
Chris@0 458
Chris@0 459 float
Martin@62 460 LADSPAPluginInstance::getControlOutputValue(size_t output) const
Chris@60 461 {
Chris@60 462 if (output > m_controlPortsOut.size()) return 0.0;
Chris@60 463 return (*m_controlPortsOut[output].second);
Chris@60 464 }
Chris@60 465
Chris@60 466 float
Chris@0 467 LADSPAPluginInstance::getParameterValue(unsigned int parameter) const
Chris@0 468 {
Chris@0 469 if (parameter >= m_controlPortsIn.size()) return 0.0;
Chris@0 470 return (*m_controlPortsIn[parameter].second);
Chris@0 471 }
Chris@0 472
Chris@0 473 float
Chris@0 474 LADSPAPluginInstance::getParameterDefault(unsigned int parameter) const
Chris@0 475 {
Chris@0 476 if (parameter >= m_controlPortsIn.size()) return 0.0;
Chris@0 477
Chris@0 478 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 479 if (f) {
Chris@0 480 return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first);
Chris@0 481 } else {
Chris@0 482 return 0.0f;
Chris@0 483 }
Chris@0 484 }
Chris@0 485
Chris@0 486 void
Chris@66 487 LADSPAPluginInstance::run(const Vamp::RealTime &)
Chris@0 488 {
Chris@0 489 if (!m_descriptor || !m_descriptor->run) return;
Chris@0 490
Chris@0 491 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 492 hi != m_instanceHandles.end(); ++hi) {
Chris@0 493 m_descriptor->run(*hi, m_blockSize);
Chris@0 494 }
Chris@0 495
Chris@0 496 m_run = true;
Chris@0 497 }
Chris@0 498
Chris@0 499 void
Chris@0 500 LADSPAPluginInstance::deactivate()
Chris@0 501 {
Chris@0 502 if (!m_descriptor || !m_descriptor->deactivate) return;
Chris@0 503
Chris@0 504 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 505 hi != m_instanceHandles.end(); ++hi) {
Chris@0 506 m_descriptor->deactivate(*hi);
Chris@0 507 }
Chris@0 508 }
Chris@0 509
Chris@0 510 void
Chris@0 511 LADSPAPluginInstance::cleanup()
Chris@0 512 {
Chris@0 513 if (!m_descriptor) return;
Chris@0 514
Chris@0 515 if (!m_descriptor->cleanup) {
Chris@0 516 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
Chris@0 517 << ":" << m_descriptor->Label
Chris@0 518 << " has no cleanup method!" << std::endl;
Chris@0 519 return;
Chris@0 520 }
Chris@0 521
Chris@0 522 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 523 hi != m_instanceHandles.end(); ++hi) {
Chris@0 524 m_descriptor->cleanup(*hi);
Chris@0 525 }
Chris@0 526
Chris@0 527 m_instanceHandles.clear();
Chris@0 528 }
Chris@0 529
Chris@0 530