DistrhoPluginLV2.cpp (59583B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any purpose with 6 * or without fee is hereby granted, provided that the above copyright notice and this 7 * permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN 11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "DistrhoPluginInternal.hpp" 18 19 #include "lv2/atom.h" 20 #include "lv2/atom-forge.h" 21 #include "lv2/atom-util.h" 22 #include "lv2/buf-size.h" 23 #include "lv2/data-access.h" 24 #include "lv2/instance-access.h" 25 #include "lv2/midi.h" 26 #include "lv2/options.h" 27 #include "lv2/parameters.h" 28 #include "lv2/patch.h" 29 #include "lv2/state.h" 30 #include "lv2/time.h" 31 #include "lv2/urid.h" 32 #include "lv2/worker.h" 33 #include "lv2/lv2_kxstudio_properties.h" 34 #include "lv2/lv2_programs.h" 35 #include "lv2/control-input-port-change-request.h" 36 37 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 38 # include "libmodla.h" 39 #endif 40 41 #include <map> 42 43 #ifndef DISTRHO_PLUGIN_URI 44 # error DISTRHO_PLUGIN_URI undefined! 45 #endif 46 47 #ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX 48 # define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" 49 #endif 50 51 #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) 52 #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE) 53 54 START_NAMESPACE_DISTRHO 55 56 typedef std::map<const String, String> StringToStringMap; 57 typedef std::map<const LV2_URID, String> UridToStringMap; 58 59 #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 60 static const writeMidiFunc writeMidiCallback = nullptr; 61 #endif 62 #if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 63 static const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; 64 #endif 65 #if ! DISTRHO_PLUGIN_WANT_STATE 66 static const updateStateValueFunc updateStateValueCallback = nullptr; 67 #endif 68 69 // ----------------------------------------------------------------------- 70 71 class PluginLv2 72 { 73 public: 74 PluginLv2(const double sampleRate, 75 const LV2_URID_Map* const uridMap, 76 const LV2_Worker_Schedule* const worker, 77 const LV2_ControlInputPort_Change_Request* const ctrlInPortChangeReq, 78 const bool usingNominal) 79 : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback), 80 fUsingNominal(usingNominal), 81 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 82 fRunCount(0), 83 #endif 84 fPortControls(nullptr), 85 fLastControlValues(nullptr), 86 fSampleRate(sampleRate), 87 fURIDs(uridMap), 88 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 89 fCtrlInPortChangeReq(ctrlInPortChangeReq), 90 #endif 91 fUridMap(uridMap), 92 fWorker(worker) 93 { 94 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 95 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) 96 fPortAudioIns[i] = nullptr; 97 #else 98 fPortAudioIns = nullptr; 99 #endif 100 101 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 102 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) 103 fPortAudioOuts[i] = nullptr; 104 #else 105 fPortAudioOuts = nullptr; 106 #endif 107 108 if (const uint32_t count = fPlugin.getParameterCount()) 109 { 110 fPortControls = new float*[count]; 111 fLastControlValues = new float[count]; 112 113 for (uint32_t i=0; i < count; ++i) 114 { 115 fPortControls[i] = nullptr; 116 fLastControlValues[i] = fPlugin.getParameterValue(i); 117 } 118 } 119 else 120 { 121 fPortControls = nullptr; 122 fLastControlValues = nullptr; 123 } 124 125 #if DISTRHO_LV2_USE_EVENTS_IN 126 fPortEventsIn = nullptr; 127 #endif 128 #if DISTRHO_PLUGIN_WANT_LATENCY 129 fPortLatency = nullptr; 130 #endif 131 132 #if DISTRHO_PLUGIN_WANT_STATE 133 std::memset(&fAtomForge, 0, sizeof(fAtomForge)); 134 lv2_atom_forge_init(&fAtomForge, uridMap); 135 136 if (const uint32_t count = fPlugin.getStateCount()) 137 { 138 fUrids = new LV2_URID[count]; 139 fNeededUiSends = new bool[count]; 140 141 for (uint32_t i=0; i < count; ++i) 142 { 143 fNeededUiSends[i] = false; 144 145 const String& statekey(fPlugin.getStateKey(i)); 146 fStateMap[statekey] = fPlugin.getStateDefaultValue(i); 147 148 const String lv2key(DISTRHO_PLUGIN_URI "#" + statekey); 149 const LV2_URID urid = fUrids[i] = uridMap->map(uridMap->handle, lv2key.buffer()); 150 fUridStateMap[urid] = statekey; 151 } 152 } 153 else 154 { 155 fUrids = nullptr; 156 fNeededUiSends = nullptr; 157 } 158 #else 159 // unused 160 (void)fWorker; 161 #endif 162 163 #if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 164 // unused 165 (void)ctrlInPortChangeReq; 166 #endif 167 } 168 169 ~PluginLv2() 170 { 171 if (fPortControls != nullptr) 172 { 173 delete[] fPortControls; 174 fPortControls = nullptr; 175 } 176 177 if (fLastControlValues) 178 { 179 delete[] fLastControlValues; 180 fLastControlValues = nullptr; 181 } 182 183 #if DISTRHO_PLUGIN_WANT_STATE 184 if (fNeededUiSends != nullptr) 185 { 186 delete[] fNeededUiSends; 187 fNeededUiSends = nullptr; 188 } 189 190 if (fUrids != nullptr) 191 { 192 delete[] fUrids; 193 fUrids = nullptr; 194 } 195 196 fStateMap.clear(); 197 #endif 198 } 199 200 // ------------------------------------------------------------------- 201 202 bool getPortControlValue(uint32_t index, float& value) const 203 { 204 if (const float* control = fPortControls[index]) 205 { 206 switch (fPlugin.getParameterDesignation(index)) 207 { 208 default: 209 value = *control; 210 break; 211 case kParameterDesignationBypass: 212 value = 1.0f - *control; 213 break; 214 } 215 216 return true; 217 } 218 219 return false; 220 } 221 222 void setPortControlValue(uint32_t index, float value) 223 { 224 if (float* control = fPortControls[index]) 225 { 226 switch (fPlugin.getParameterDesignation(index)) 227 { 228 default: 229 *control = value; 230 break; 231 case kParameterDesignationBypass: 232 *control = 1.0f - value; 233 break; 234 } 235 } 236 } 237 238 // ------------------------------------------------------------------- 239 240 void lv2_activate() 241 { 242 #if DISTRHO_PLUGIN_WANT_TIMEPOS 243 fTimePosition.clear(); 244 245 // hosts may not send all values, resulting on some invalid data, let's reset everything 246 fTimePosition.bbt.bar = 1; 247 fTimePosition.bbt.beat = 1; 248 fTimePosition.bbt.tick = 0.0; 249 fTimePosition.bbt.barStartTick = 0; 250 fTimePosition.bbt.beatsPerBar = 4; 251 fTimePosition.bbt.beatType = 4; 252 fTimePosition.bbt.ticksPerBeat = 1920.0; 253 fTimePosition.bbt.beatsPerMinute = 120.0; 254 #endif 255 fPlugin.activate(); 256 } 257 258 void lv2_deactivate() 259 { 260 fPlugin.deactivate(); 261 } 262 263 // ------------------------------------------------------------------- 264 265 void lv2_connect_port(const uint32_t port, void* const dataLocation) 266 { 267 uint32_t index = 0; 268 269 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 270 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) 271 { 272 if (port == index++) 273 { 274 fPortAudioIns[i] = (const float*)dataLocation; 275 return; 276 } 277 } 278 #endif 279 280 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 281 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) 282 { 283 if (port == index++) 284 { 285 fPortAudioOuts[i] = (float*)dataLocation; 286 return; 287 } 288 } 289 #endif 290 291 #if DISTRHO_LV2_USE_EVENTS_IN 292 if (port == index++) 293 { 294 fPortEventsIn = (LV2_Atom_Sequence*)dataLocation; 295 return; 296 } 297 #endif 298 299 #if DISTRHO_LV2_USE_EVENTS_OUT 300 if (port == index++) 301 { 302 fEventsOutData.port = (LV2_Atom_Sequence*)dataLocation; 303 return; 304 } 305 #endif 306 307 #if DISTRHO_PLUGIN_WANT_LATENCY 308 if (port == index++) 309 { 310 fPortLatency = (float*)dataLocation; 311 return; 312 } 313 #endif 314 315 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) 316 { 317 if (port == index++) 318 { 319 fPortControls[i] = (float*)dataLocation; 320 return; 321 } 322 } 323 } 324 325 // ------------------------------------------------------------------- 326 327 void lv2_run(const uint32_t sampleCount) 328 { 329 // cache midi input and time position first 330 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT 331 uint32_t midiEventCount = 0; 332 #endif 333 334 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS 335 LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) 336 { 337 if (event == nullptr) 338 break; 339 340 # if DISTRHO_PLUGIN_WANT_MIDI_INPUT 341 if (event->body.type == fURIDs.midiEvent) 342 { 343 if (midiEventCount >= kMaxMidiEvents) 344 continue; 345 346 const uint8_t* const data((const uint8_t*)(event + 1)); 347 348 MidiEvent& midiEvent(fMidiEvents[midiEventCount++]); 349 350 midiEvent.frame = event->time.frames; 351 midiEvent.size = event->body.size; 352 353 if (midiEvent.size > MidiEvent::kDataSize) 354 { 355 midiEvent.dataExt = data; 356 std::memset(midiEvent.data, 0, MidiEvent::kDataSize); 357 } 358 else 359 { 360 midiEvent.dataExt = nullptr; 361 std::memcpy(midiEvent.data, data, midiEvent.size); 362 } 363 364 continue; 365 } 366 # endif 367 # if DISTRHO_PLUGIN_WANT_TIMEPOS 368 if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject) 369 { 370 const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body); 371 372 if (obj->body.otype != fURIDs.timePosition) 373 continue; 374 375 LV2_Atom* bar = nullptr; 376 LV2_Atom* barBeat = nullptr; 377 LV2_Atom* beatUnit = nullptr; 378 LV2_Atom* beatsPerBar = nullptr; 379 LV2_Atom* beatsPerMinute = nullptr; 380 LV2_Atom* frame = nullptr; 381 LV2_Atom* speed = nullptr; 382 LV2_Atom* ticksPerBeat = nullptr; 383 384 lv2_atom_object_get(obj, 385 fURIDs.timeBar, &bar, 386 fURIDs.timeBarBeat, &barBeat, 387 fURIDs.timeBeatUnit, &beatUnit, 388 fURIDs.timeBeatsPerBar, &beatsPerBar, 389 fURIDs.timeBeatsPerMinute, &beatsPerMinute, 390 fURIDs.timeFrame, &frame, 391 fURIDs.timeSpeed, &speed, 392 fURIDs.timeTicksPerBeat, &ticksPerBeat, 393 0); 394 395 // need to handle this first as other values depend on it 396 if (ticksPerBeat != nullptr) 397 { 398 /**/ if (ticksPerBeat->type == fURIDs.atomDouble) 399 fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body; 400 else if (ticksPerBeat->type == fURIDs.atomFloat) 401 fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body; 402 else if (ticksPerBeat->type == fURIDs.atomInt) 403 fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body; 404 else if (ticksPerBeat->type == fURIDs.atomLong) 405 fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body; 406 else 407 d_stderr("Unknown lv2 ticksPerBeat value type"); 408 409 if (fLastPositionData.ticksPerBeat > 0.0) 410 fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat; 411 } 412 413 // same 414 if (speed != nullptr) 415 { 416 /**/ if (speed->type == fURIDs.atomDouble) 417 fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body; 418 else if (speed->type == fURIDs.atomFloat) 419 fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body; 420 else if (speed->type == fURIDs.atomInt) 421 fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body; 422 else if (speed->type == fURIDs.atomLong) 423 fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body; 424 else 425 d_stderr("Unknown lv2 speed value type"); 426 427 fTimePosition.playing = d_isNotZero(fLastPositionData.speed); 428 } 429 430 if (bar != nullptr) 431 { 432 /**/ if (bar->type == fURIDs.atomDouble) 433 fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body; 434 else if (bar->type == fURIDs.atomFloat) 435 fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body; 436 else if (bar->type == fURIDs.atomInt) 437 fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body; 438 else if (bar->type == fURIDs.atomLong) 439 fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body; 440 else 441 d_stderr("Unknown lv2 bar value type"); 442 443 if (fLastPositionData.bar >= 0) 444 fTimePosition.bbt.bar = fLastPositionData.bar + 1; 445 } 446 447 if (barBeat != nullptr) 448 { 449 /**/ if (barBeat->type == fURIDs.atomDouble) 450 fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body; 451 else if (barBeat->type == fURIDs.atomFloat) 452 fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body; 453 else if (barBeat->type == fURIDs.atomInt) 454 fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body; 455 else if (barBeat->type == fURIDs.atomLong) 456 fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body; 457 else 458 d_stderr("Unknown lv2 barBeat value type"); 459 460 if (fLastPositionData.barBeat >= 0.0f) 461 { 462 const double rest = std::fmod(fLastPositionData.barBeat, 1.0); 463 fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat - rest + 1.0); 464 fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; 465 } 466 } 467 468 if (beatUnit != nullptr) 469 { 470 /**/ if (beatUnit->type == fURIDs.atomDouble) 471 fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body; 472 else if (beatUnit->type == fURIDs.atomFloat) 473 fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body; 474 else if (beatUnit->type == fURIDs.atomInt) 475 fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body; 476 else if (beatUnit->type == fURIDs.atomLong) 477 fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body; 478 else 479 d_stderr("Unknown lv2 beatUnit value type"); 480 481 if (fLastPositionData.beatUnit > 0) 482 fTimePosition.bbt.beatType = fLastPositionData.beatUnit; 483 } 484 485 if (beatsPerBar != nullptr) 486 { 487 /**/ if (beatsPerBar->type == fURIDs.atomDouble) 488 fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; 489 else if (beatsPerBar->type == fURIDs.atomFloat) 490 fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; 491 else if (beatsPerBar->type == fURIDs.atomInt) 492 fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; 493 else if (beatsPerBar->type == fURIDs.atomLong) 494 fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; 495 else 496 d_stderr("Unknown lv2 beatsPerBar value type"); 497 498 if (fLastPositionData.beatsPerBar > 0.0f) 499 fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar; 500 } 501 502 if (beatsPerMinute != nullptr) 503 { 504 /**/ if (beatsPerMinute->type == fURIDs.atomDouble) 505 fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; 506 else if (beatsPerMinute->type == fURIDs.atomFloat) 507 fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; 508 else if (beatsPerMinute->type == fURIDs.atomInt) 509 fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; 510 else if (beatsPerMinute->type == fURIDs.atomLong) 511 fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; 512 else 513 d_stderr("Unknown lv2 beatsPerMinute value type"); 514 515 if (fLastPositionData.beatsPerMinute > 0.0f) 516 { 517 fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute; 518 519 if (d_isNotZero(fLastPositionData.speed)) 520 fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed); 521 } 522 } 523 524 if (frame != nullptr) 525 { 526 /**/ if (frame->type == fURIDs.atomDouble) 527 fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body; 528 else if (frame->type == fURIDs.atomFloat) 529 fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body; 530 else if (frame->type == fURIDs.atomInt) 531 fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body; 532 else if (frame->type == fURIDs.atomLong) 533 fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body; 534 else 535 d_stderr("Unknown lv2 frame value type"); 536 537 if (fLastPositionData.frame >= 0) 538 fTimePosition.frame = fLastPositionData.frame; 539 } 540 541 fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* 542 fTimePosition.bbt.beatsPerBar* 543 (fTimePosition.bbt.bar-1); 544 545 fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 && 546 fLastPositionData.beatUnit > 0 && 547 fLastPositionData.beatsPerBar > 0.0f); 548 549 fPlugin.setTimePosition(fTimePosition); 550 551 continue; 552 } 553 # endif 554 } 555 #endif 556 557 // check for messages from UI or host 558 #if DISTRHO_PLUGIN_WANT_STATE 559 LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) 560 { 561 if (event == nullptr) 562 break; 563 564 #if DISTRHO_PLUGIN_HAS_UI 565 if (event->body.type == fURIDs.dpfKeyValue) 566 { 567 const void* const data = (const void*)(event + 1); 568 569 // check if this is our special message 570 if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0) 571 { 572 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 573 { 574 if (fPlugin.getStateHints(i) & kStateIsOnlyForDSP) 575 continue; 576 fNeededUiSends[i] = true; 577 } 578 } 579 // no, send to DSP as usual 580 else if (fWorker != nullptr) 581 { 582 fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); 583 } 584 } 585 else 586 #endif 587 if (event->body.type == fURIDs.atomObject && fWorker != nullptr) 588 { 589 const LV2_Atom_Object* const object = (const LV2_Atom_Object*)&event->body; 590 591 const LV2_Atom* property = nullptr; 592 const LV2_Atom* value = nullptr; 593 lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); 594 595 if (property != nullptr && property->type == fURIDs.atomURID && 596 value != nullptr && (value->type == fURIDs.atomPath || value->type == fURIDs.atomString)) 597 { 598 fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); 599 } 600 } 601 } 602 #endif 603 604 // Check for updated parameters 605 float curValue; 606 607 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) 608 { 609 if (!getPortControlValue(i, curValue)) 610 continue; 611 612 if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue)) 613 { 614 fLastControlValues[i] = curValue; 615 616 fPlugin.setParameterValue(i, curValue); 617 } 618 } 619 620 // Run plugin 621 if (sampleCount != 0) 622 { 623 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 624 fRunCount = mod_license_run_begin(fRunCount, sampleCount); 625 #endif 626 627 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT 628 fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); 629 #else 630 fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); 631 #endif 632 633 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 634 for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) 635 mod_license_run_silence(fRunCount, fPortAudioOuts[i], sampleCount, i); 636 #endif 637 638 #if DISTRHO_PLUGIN_WANT_TIMEPOS 639 // update timePos for next callback 640 if (d_isNotZero(fLastPositionData.speed)) 641 { 642 if (fLastPositionData.speed > 0.0) 643 { 644 // playing forwards 645 fLastPositionData.frame += sampleCount; 646 } 647 else 648 { 649 // playing backwards 650 fLastPositionData.frame -= sampleCount; 651 652 if (fLastPositionData.frame < 0) 653 fLastPositionData.frame = 0; 654 } 655 656 fTimePosition.frame = fLastPositionData.frame; 657 658 if (fTimePosition.bbt.valid) 659 { 660 const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed; 661 const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute; 662 const double addedBarBeats = double(sampleCount) / framesPerBeat; 663 664 if (fLastPositionData.barBeat >= 0.0f) 665 { 666 fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats, 667 (double)fLastPositionData.beatsPerBar); 668 669 const double rest = std::fmod(fLastPositionData.barBeat, 1.0f); 670 fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat - rest + 1.0); 671 fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; 672 673 if (fLastPositionData.bar >= 0) 674 { 675 fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/ 676 fLastPositionData.beatsPerBar); 677 678 if (fLastPositionData.bar < 0) 679 fLastPositionData.bar = 0; 680 681 fTimePosition.bbt.bar = fLastPositionData.bar + 1; 682 683 fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* 684 fTimePosition.bbt.beatsPerBar* 685 (fTimePosition.bbt.bar-1); 686 } 687 } 688 689 fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute); 690 } 691 692 fPlugin.setTimePosition(fTimePosition); 693 } 694 #endif 695 } 696 697 updateParameterOutputsAndTriggers(); 698 699 #if DISTRHO_PLUGIN_WANT_STATE 700 fEventsOutData.initIfNeeded(fURIDs.atomSequence); 701 702 LV2_Atom_Event* aev; 703 const uint32_t capacity = fEventsOutData.capacity; 704 705 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 706 { 707 if (! fNeededUiSends[i]) 708 continue; 709 710 const uint32_t hints = fPlugin.getStateHints(i); 711 712 #if ! DISTRHO_PLUGIN_HAS_UI 713 if ((hints & kStateIsHostReadable) == 0x0) 714 { 715 fNeededUiSends[i] = false; 716 continue; 717 } 718 #endif 719 720 const String& curKey(fPlugin.getStateKey(i)); 721 722 for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) 723 { 724 const String& key(cit->first); 725 726 if (curKey != key) 727 continue; 728 729 const String& value(cit->second); 730 731 // set msg size 732 uint32_t msgSize; 733 734 if (hints & kStateIsHostReadable) 735 { 736 // object, prop key, prop urid, value key, value 737 msgSize = sizeof(LV2_Atom_Object) 738 + sizeof(LV2_Atom_Property_Body) * 4 739 + sizeof(LV2_Atom_URID) * 3 740 + sizeof(LV2_Atom_String) 741 + value.length() + 1; 742 } 743 else 744 { 745 // key + value + 2x null terminator + separator 746 msgSize = static_cast<uint32_t>(key.length()+value.length())+3U; 747 } 748 749 if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset) 750 { 751 d_stdout("Sending key '%s' to UI failed, out of space (needs %u bytes)", 752 key.buffer(), msgSize); 753 break; 754 } 755 756 // put data 757 aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset); 758 aev->time.frames = 0; 759 760 if (hints & kStateIsHostReadable) 761 { 762 uint8_t* const msgBuf = (uint8_t*)&aev->body; 763 LV2_Atom_Forge atomForge = fAtomForge; 764 lv2_atom_forge_set_buffer(&atomForge, msgBuf, msgSize); 765 766 LV2_Atom_Forge_Frame forgeFrame; 767 lv2_atom_forge_object(&atomForge, &forgeFrame, 0, fURIDs.patchSet); 768 769 lv2_atom_forge_key(&atomForge, fURIDs.patchProperty); 770 lv2_atom_forge_urid(&atomForge, fUrids[i]); 771 772 lv2_atom_forge_key(&atomForge, fURIDs.patchValue); 773 if ((hints & kStateIsFilenamePath) == kStateIsFilenamePath) 774 lv2_atom_forge_path(&atomForge, value.buffer(), static_cast<uint32_t>(value.length()+1)); 775 else 776 lv2_atom_forge_string(&atomForge, value.buffer(), static_cast<uint32_t>(value.length()+1)); 777 778 lv2_atom_forge_pop(&atomForge, &forgeFrame); 779 780 msgSize = ((LV2_Atom*)msgBuf)->size; 781 } 782 else 783 { 784 aev->body.type = fURIDs.dpfKeyValue; 785 aev->body.size = msgSize; 786 787 uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body); 788 std::memset(msgBuf, 0, msgSize); 789 790 // write key and value in atom buffer 791 std::memcpy(msgBuf, key.buffer(), key.length()+1); 792 std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1); 793 } 794 795 fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize)); 796 fNeededUiSends[i] = false; 797 break; 798 } 799 } 800 #endif 801 802 #if DISTRHO_LV2_USE_EVENTS_OUT 803 fEventsOutData.endRun(); 804 #endif 805 } 806 807 // ------------------------------------------------------------------- 808 809 uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) 810 { 811 // currently unused 812 return LV2_OPTIONS_ERR_UNKNOWN; 813 } 814 815 uint32_t lv2_set_options(const LV2_Options_Option* const options) 816 { 817 for (int i=0; options[i].key != 0; ++i) 818 { 819 if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength)) 820 { 821 if (options[i].type == fURIDs.atomInt) 822 { 823 const int32_t bufferSize(*(const int32_t*)options[i].value); 824 fPlugin.setBufferSize(bufferSize, true); 825 } 826 else 827 { 828 d_stderr("Host changed nominalBlockLength but with wrong value type"); 829 } 830 } 831 else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal) 832 { 833 if (options[i].type == fURIDs.atomInt) 834 { 835 const int32_t bufferSize(*(const int32_t*)options[i].value); 836 fPlugin.setBufferSize(bufferSize, true); 837 } 838 else 839 { 840 d_stderr("Host changed maxBlockLength but with wrong value type"); 841 } 842 } 843 else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate)) 844 { 845 if (options[i].type == fURIDs.atomFloat) 846 { 847 const float sampleRate(*(const float*)options[i].value); 848 fSampleRate = sampleRate; 849 fPlugin.setSampleRate(sampleRate, true); 850 } 851 else 852 { 853 d_stderr("Host changed sampleRate but with wrong value type"); 854 } 855 } 856 } 857 858 return LV2_OPTIONS_SUCCESS; 859 } 860 861 // ------------------------------------------------------------------- 862 863 #if DISTRHO_PLUGIN_WANT_PROGRAMS 864 const LV2_Program_Descriptor* lv2_get_program(const uint32_t index) 865 { 866 if (index >= fPlugin.getProgramCount()) 867 return nullptr; 868 869 static LV2_Program_Descriptor desc; 870 871 desc.bank = index / 128; 872 desc.program = index % 128; 873 desc.name = fPlugin.getProgramName(index); 874 875 return &desc; 876 } 877 878 void lv2_select_program(const uint32_t bank, const uint32_t program) 879 { 880 const uint32_t realProgram(bank * 128 + program); 881 882 if (realProgram >= fPlugin.getProgramCount()) 883 return; 884 885 fPlugin.loadProgram(realProgram); 886 887 // Update control inputs 888 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) 889 { 890 if (fPlugin.isParameterOutput(i)) 891 continue; 892 893 fLastControlValues[i] = fPlugin.getParameterValue(i); 894 895 setPortControlValue(i, fLastControlValues[i]); 896 } 897 898 #if DISTRHO_PLUGIN_WANT_FULL_STATE 899 // Update state 900 for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) 901 { 902 const String& key = cit->first; 903 fStateMap[key] = fPlugin.getStateValue(key); 904 } 905 #endif 906 } 907 #endif 908 909 // ------------------------------------------------------------------- 910 911 #if DISTRHO_PLUGIN_WANT_STATE 912 LV2_State_Status lv2_save(const LV2_State_Store_Function store, 913 const LV2_State_Handle handle, 914 const LV2_Feature* const* const features) 915 { 916 #if DISTRHO_PLUGIN_WANT_FULL_STATE 917 // Update current state 918 for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) 919 { 920 const String& key = cit->first; 921 fStateMap[key] = fPlugin.getStateValue(key); 922 } 923 #endif 924 925 String lv2key; 926 LV2_URID urid; 927 928 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 929 { 930 const String& curKey(fPlugin.getStateKey(i)); 931 932 for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) 933 { 934 const String& key(cit->first); 935 936 if (curKey != key) 937 continue; 938 939 const uint32_t hints = fPlugin.getStateHints(i); 940 941 #if ! DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 942 // do not save UI-only messages if there is no UI available 943 if (hints & kStateIsOnlyForUI) 944 break; 945 #endif 946 947 if (hints & kStateIsHostReadable) 948 { 949 lv2key = DISTRHO_PLUGIN_URI "#"; 950 urid = (hints & kStateIsFilenamePath) == kStateIsFilenamePath 951 ? fURIDs.atomPath 952 : fURIDs.atomString; 953 } 954 else 955 { 956 lv2key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; 957 urid = fURIDs.atomString; 958 } 959 960 lv2key += key; 961 962 const String& value(cit->second); 963 964 if (urid == fURIDs.atomPath) 965 { 966 const LV2_State_Map_Path* mapPath = nullptr; 967 const LV2_State_Free_Path* freePath = nullptr; 968 for (int i=0; features[i] != nullptr; ++i) 969 { 970 if (std::strcmp(features[i]->URI, LV2_STATE__mapPath) == 0) 971 mapPath = (const LV2_State_Map_Path*)features[i]->data; 972 else if (std::strcmp(features[i]->URI, LV2_STATE__freePath) == 0) 973 freePath = (const LV2_State_Free_Path*)features[i]->data; 974 } 975 976 if (char* const abstractPath = mapPath != nullptr 977 ? mapPath->abstract_path(mapPath->handle, value.buffer()) 978 : nullptr) 979 { 980 // some hosts need +1 for the null terminator, even though the type is string/path 981 store(handle, 982 fUridMap->map(fUridMap->handle, lv2key.buffer()), 983 abstractPath, 984 std::strlen(abstractPath)+1, 985 urid, 986 LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); 987 988 if (freePath != nullptr) 989 freePath->free_path(freePath->handle, abstractPath); 990 #ifndef DISTRHO_OS_WINDOWS 991 else 992 std::free(abstractPath); 993 #endif 994 995 break; 996 } 997 } 998 999 // some hosts need +1 for the null terminator, even though the type is string 1000 store(handle, 1001 fUridMap->map(fUridMap->handle, lv2key.buffer()), 1002 value.buffer(), 1003 value.length()+1, 1004 urid, 1005 LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); 1006 1007 break; 1008 } 1009 } 1010 1011 return LV2_STATE_SUCCESS; 1012 } 1013 1014 LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, 1015 const LV2_State_Handle handle, 1016 const LV2_Feature* const* const features) 1017 { 1018 size_t size; 1019 uint32_t type, flags; 1020 1021 String lv2key; 1022 LV2_URID urid; 1023 1024 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 1025 { 1026 const String& key(fPlugin.getStateKey(i)); 1027 1028 const uint32_t hints = fPlugin.getStateHints(i); 1029 1030 if (hints & kStateIsHostReadable) 1031 { 1032 lv2key = DISTRHO_PLUGIN_URI "#"; 1033 urid = (hints & kStateIsFilenamePath) == kStateIsFilenamePath 1034 ? fURIDs.atomPath 1035 : fURIDs.atomString; 1036 } 1037 else 1038 { 1039 lv2key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; 1040 urid = fURIDs.atomString; 1041 } 1042 1043 lv2key += key; 1044 1045 size = 0; 1046 type = 0; 1047 flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; 1048 const void* data = retrieve(handle, 1049 fUridMap->map(fUridMap->handle, lv2key.buffer()), 1050 &size, &type, &flags); 1051 1052 if (data == nullptr || size == 0) 1053 continue; 1054 1055 DISTRHO_SAFE_ASSERT_CONTINUE(type == urid); 1056 1057 const char* const value = (const char*)data; 1058 const std::size_t length = std::strlen(value); 1059 DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); 1060 1061 if (urid == fURIDs.atomPath) 1062 { 1063 const LV2_State_Map_Path* mapPath = nullptr; 1064 const LV2_State_Free_Path* freePath = nullptr; 1065 for (int i=0; features[i] != nullptr; ++i) 1066 { 1067 if (std::strcmp(features[i]->URI, LV2_STATE__mapPath) == 0) 1068 mapPath = (const LV2_State_Map_Path*)features[i]->data; 1069 else if (std::strcmp(features[i]->URI, LV2_STATE__freePath) == 0) 1070 freePath = (const LV2_State_Free_Path*)features[i]->data; 1071 } 1072 1073 if (char* const absolutePath = mapPath != nullptr 1074 ? mapPath->absolute_path(mapPath->handle, value) 1075 : nullptr) 1076 { 1077 setState(key, absolutePath); 1078 1079 if (freePath != nullptr) 1080 freePath->free_path(freePath->handle, absolutePath); 1081 #ifndef DISTRHO_OS_WINDOWS 1082 else 1083 std::free(absolutePath); 1084 #endif 1085 1086 // signal msg needed for UI 1087 fNeededUiSends[i] = true; 1088 continue; 1089 } 1090 } 1091 1092 setState(key, value); 1093 1094 #if DISTRHO_PLUGIN_WANT_STATE 1095 // signal msg needed for UI 1096 if ((hints & kStateIsOnlyForDSP) == 0x0) 1097 fNeededUiSends[i] = true; 1098 #endif 1099 } 1100 1101 return LV2_STATE_SUCCESS; 1102 } 1103 1104 // ------------------------------------------------------------------- 1105 1106 LV2_Worker_Status lv2_work(const void* const data) 1107 { 1108 const LV2_Atom* const eventBody = (const LV2_Atom*)data; 1109 1110 if (eventBody->type == fURIDs.dpfKeyValue) 1111 { 1112 const char* const key = (const char*)(eventBody + 1); 1113 const char* const value = key + (std::strlen(key) + 1U); 1114 1115 setState(key, value); 1116 return LV2_WORKER_SUCCESS; 1117 } 1118 1119 if (eventBody->type == fURIDs.atomObject) 1120 { 1121 const LV2_Atom_Object* const object = (const LV2_Atom_Object*)eventBody; 1122 1123 const LV2_Atom* property = nullptr; 1124 const LV2_Atom* value = nullptr; 1125 lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); 1126 DISTRHO_SAFE_ASSERT_RETURN(property != nullptr, LV2_WORKER_ERR_UNKNOWN); 1127 DISTRHO_SAFE_ASSERT_RETURN(property->type == fURIDs.atomURID, LV2_WORKER_ERR_UNKNOWN); 1128 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr, LV2_WORKER_ERR_UNKNOWN); 1129 DISTRHO_SAFE_ASSERT_RETURN(value->type == fURIDs.atomPath || 1130 value->type == fURIDs.atomString, LV2_WORKER_ERR_UNKNOWN); 1131 1132 const LV2_URID urid = ((const LV2_Atom_URID*)property)->body; 1133 const char* const filename = (const char*)(value + 1); 1134 1135 String key; 1136 1137 try { 1138 key = fUridStateMap[urid]; 1139 } DISTRHO_SAFE_EXCEPTION_RETURN("lv2_work fUridStateMap[urid]", LV2_WORKER_ERR_UNKNOWN); 1140 1141 setState(key, filename); 1142 1143 /* FIXME host should be responsible for updating UI side, not us 1144 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 1145 { 1146 if (fPlugin.getStateKey(i) == key) 1147 { 1148 if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0) 1149 fNeededUiSends[i] = true; 1150 break; 1151 } 1152 } 1153 */ 1154 1155 return LV2_WORKER_SUCCESS; 1156 } 1157 1158 return LV2_WORKER_ERR_UNKNOWN; 1159 } 1160 1161 LV2_Worker_Status lv2_work_response(uint32_t, const void*) 1162 { 1163 return LV2_WORKER_SUCCESS; 1164 } 1165 #endif 1166 1167 // ------------------------------------------------------------------- 1168 1169 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1170 void* lv2_get_instance_pointer() 1171 { 1172 return fPlugin.getInstancePointer(); 1173 } 1174 #endif 1175 1176 // ------------------------------------------------------------------- 1177 1178 private: 1179 PluginExporter fPlugin; 1180 const bool fUsingNominal; // if false use maxBlockLength 1181 1182 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 1183 uint32_t fRunCount; 1184 #endif 1185 1186 // LV2 ports 1187 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 1188 const float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; 1189 #else 1190 const float** fPortAudioIns; 1191 #endif 1192 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 1193 float* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; 1194 #else 1195 float** fPortAudioOuts; 1196 #endif 1197 float** fPortControls; 1198 #if DISTRHO_LV2_USE_EVENTS_IN 1199 LV2_Atom_Sequence* fPortEventsIn; 1200 #endif 1201 #if DISTRHO_PLUGIN_WANT_LATENCY 1202 float* fPortLatency; 1203 #endif 1204 1205 // Temporary data 1206 float* fLastControlValues; 1207 double fSampleRate; 1208 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT 1209 MidiEvent fMidiEvents[kMaxMidiEvents]; 1210 #endif 1211 #if DISTRHO_PLUGIN_WANT_TIMEPOS 1212 TimePosition fTimePosition; 1213 1214 struct Lv2PositionData { 1215 int64_t bar; 1216 float barBeat; 1217 uint32_t beatUnit; 1218 float beatsPerBar; 1219 float beatsPerMinute; 1220 int64_t frame; 1221 double speed; 1222 double ticksPerBeat; 1223 1224 Lv2PositionData() 1225 : bar(-1), 1226 barBeat(-1.0f), 1227 beatUnit(0), 1228 beatsPerBar(0.0f), 1229 beatsPerMinute(0.0f), 1230 frame(-1), 1231 speed(0.0), 1232 ticksPerBeat(-1.0) {} 1233 1234 } fLastPositionData; 1235 #endif 1236 1237 #if DISTRHO_LV2_USE_EVENTS_OUT 1238 struct Lv2EventsOutData { 1239 uint32_t capacity, offset; 1240 LV2_Atom_Sequence* port; 1241 1242 Lv2EventsOutData() 1243 : capacity(0), 1244 offset(0), 1245 port(nullptr) {} 1246 1247 void initIfNeeded(const LV2_URID uridAtomSequence) 1248 { 1249 if (capacity != 0) 1250 return; 1251 1252 capacity = port->atom.size; 1253 1254 port->atom.size = sizeof(LV2_Atom_Sequence_Body); 1255 port->atom.type = uridAtomSequence; 1256 port->body.unit = 0; 1257 port->body.pad = 0; 1258 } 1259 1260 void growBy(const uint32_t size) 1261 { 1262 offset += size; 1263 port->atom.size += size; 1264 } 1265 1266 void endRun() 1267 { 1268 capacity = 0; 1269 offset = 0; 1270 } 1271 1272 } fEventsOutData; 1273 #endif 1274 1275 // LV2 URIDs 1276 struct URIDs { 1277 const LV2_URID_Map* _uridMap; 1278 LV2_URID atomBlank; 1279 LV2_URID atomObject; 1280 LV2_URID atomDouble; 1281 LV2_URID atomFloat; 1282 LV2_URID atomInt; 1283 LV2_URID atomLong; 1284 LV2_URID atomPath; 1285 LV2_URID atomSequence; 1286 LV2_URID atomString; 1287 LV2_URID atomURID; 1288 LV2_URID dpfKeyValue; 1289 LV2_URID midiEvent; 1290 LV2_URID patchSet; 1291 LV2_URID patchProperty; 1292 LV2_URID patchValue; 1293 LV2_URID timePosition; 1294 LV2_URID timeBar; 1295 LV2_URID timeBarBeat; 1296 LV2_URID timeBeatUnit; 1297 LV2_URID timeBeatsPerBar; 1298 LV2_URID timeBeatsPerMinute; 1299 LV2_URID timeTicksPerBeat; 1300 LV2_URID timeFrame; 1301 LV2_URID timeSpeed; 1302 1303 URIDs(const LV2_URID_Map* const uridMap) 1304 : _uridMap(uridMap), 1305 atomBlank(map(LV2_ATOM__Blank)), 1306 atomObject(map(LV2_ATOM__Object)), 1307 atomDouble(map(LV2_ATOM__Double)), 1308 atomFloat(map(LV2_ATOM__Float)), 1309 atomInt(map(LV2_ATOM__Int)), 1310 atomLong(map(LV2_ATOM__Long)), 1311 atomPath(map(LV2_ATOM__Path)), 1312 atomSequence(map(LV2_ATOM__Sequence)), 1313 atomString(map(LV2_ATOM__String)), 1314 atomURID(map(LV2_ATOM__URID)), 1315 dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), 1316 midiEvent(map(LV2_MIDI__MidiEvent)), 1317 patchSet(map(LV2_PATCH__Set)), 1318 patchProperty(map(LV2_PATCH__property)), 1319 patchValue(map(LV2_PATCH__value)), 1320 timePosition(map(LV2_TIME__Position)), 1321 timeBar(map(LV2_TIME__bar)), 1322 timeBarBeat(map(LV2_TIME__barBeat)), 1323 timeBeatUnit(map(LV2_TIME__beatUnit)), 1324 timeBeatsPerBar(map(LV2_TIME__beatsPerBar)), 1325 timeBeatsPerMinute(map(LV2_TIME__beatsPerMinute)), 1326 timeTicksPerBeat(map(LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)), 1327 timeFrame(map(LV2_TIME__frame)), 1328 timeSpeed(map(LV2_TIME__speed)) {} 1329 1330 inline LV2_URID map(const char* const uri) const 1331 { 1332 return _uridMap->map(_uridMap->handle, uri); 1333 } 1334 } fURIDs; 1335 1336 // LV2 features 1337 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 1338 const LV2_ControlInputPort_Change_Request* const fCtrlInPortChangeReq; 1339 #endif 1340 const LV2_URID_Map* const fUridMap; 1341 const LV2_Worker_Schedule* const fWorker; 1342 1343 #if DISTRHO_PLUGIN_WANT_STATE 1344 LV2_Atom_Forge fAtomForge; 1345 StringToStringMap fStateMap; 1346 UridToStringMap fUridStateMap; 1347 LV2_URID* fUrids; 1348 bool* fNeededUiSends; 1349 1350 void setState(const char* const key, const char* const newValue) 1351 { 1352 fPlugin.setState(key, newValue); 1353 1354 // save this key if necessary 1355 if (fPlugin.wantStateKey(key)) 1356 { 1357 const String dkey(key); 1358 fStateMap[dkey] = newValue; 1359 } 1360 } 1361 1362 bool updateState(const char* const key, const char* const newValue) 1363 { 1364 fPlugin.setState(key, newValue); 1365 1366 // key must already exist 1367 for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) 1368 { 1369 if (fPlugin.getStateKey(i) == key) 1370 { 1371 const String dkey(key); 1372 fStateMap[dkey] = newValue; 1373 1374 if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0) 1375 fNeededUiSends[i] = true; 1376 1377 return true; 1378 } 1379 } 1380 1381 d_stderr("Failed to find plugin state with key \"%s\"", key); 1382 return false; 1383 } 1384 #endif 1385 1386 void updateParameterOutputsAndTriggers() 1387 { 1388 float curValue; 1389 1390 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) 1391 { 1392 if (fPlugin.isParameterOutput(i)) 1393 { 1394 curValue = fLastControlValues[i] = fPlugin.getParameterValue(i); 1395 1396 setPortControlValue(i, curValue); 1397 } 1398 else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) 1399 { 1400 // NOTE: host is responsible for auto-updating control port buffers 1401 } 1402 } 1403 1404 #if DISTRHO_PLUGIN_WANT_LATENCY 1405 if (fPortLatency != nullptr) 1406 *fPortLatency = fPlugin.getLatency(); 1407 #endif 1408 } 1409 1410 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 1411 bool requestParameterValueChange(const uint32_t index, const float value) 1412 { 1413 if (fCtrlInPortChangeReq == nullptr) 1414 return false; 1415 return fCtrlInPortChangeReq->request_change(fCtrlInPortChangeReq->handle, 1416 index + fPlugin.getParameterOffset(), 1417 value); 1418 } 1419 1420 static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) 1421 { 1422 return (((PluginLv2*)ptr)->requestParameterValueChange(index, value) == 0); 1423 } 1424 #endif 1425 1426 #if DISTRHO_PLUGIN_WANT_STATE 1427 static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) 1428 { 1429 return ((PluginLv2*)ptr)->updateState(key, value); 1430 } 1431 #endif 1432 1433 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1434 bool writeMidi(const MidiEvent& midiEvent) 1435 { 1436 DISTRHO_SAFE_ASSERT_RETURN(fEventsOutData.port != nullptr, false); 1437 1438 fEventsOutData.initIfNeeded(fURIDs.atomSequence); 1439 1440 const uint32_t capacity = fEventsOutData.capacity; 1441 const uint32_t offset = fEventsOutData.offset; 1442 1443 if (sizeof(LV2_Atom_Event) + midiEvent.size > capacity - offset) 1444 return false; 1445 1446 LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset); 1447 aev->time.frames = midiEvent.frame; 1448 aev->body.type = fURIDs.midiEvent; 1449 aev->body.size = midiEvent.size; 1450 std::memcpy(LV2_ATOM_BODY(&aev->body), 1451 midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data, 1452 midiEvent.size); 1453 1454 fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEvent.size)); 1455 1456 return true; 1457 } 1458 1459 static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent) 1460 { 1461 return ((PluginLv2*)ptr)->writeMidi(midiEvent); 1462 } 1463 #endif 1464 }; 1465 1466 // ----------------------------------------------------------------------- 1467 1468 static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features) 1469 { 1470 const LV2_Options_Option* options = nullptr; 1471 const LV2_URID_Map* uridMap = nullptr; 1472 const LV2_Worker_Schedule* worker = nullptr; 1473 const LV2_ControlInputPort_Change_Request* ctrlInPortChangeReq = nullptr; 1474 1475 for (int i=0; features[i] != nullptr; ++i) 1476 { 1477 if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) 1478 options = (const LV2_Options_Option*)features[i]->data; 1479 else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) 1480 uridMap = (const LV2_URID_Map*)features[i]->data; 1481 else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0) 1482 worker = (const LV2_Worker_Schedule*)features[i]->data; 1483 else if (std::strcmp(features[i]->URI, LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI) == 0) 1484 ctrlInPortChangeReq = (const LV2_ControlInputPort_Change_Request*)features[i]->data; 1485 } 1486 1487 if (options == nullptr) 1488 { 1489 d_stderr("Options feature missing, cannot continue!"); 1490 return nullptr; 1491 } 1492 1493 if (uridMap == nullptr) 1494 { 1495 d_stderr("URID Map feature missing, cannot continue!"); 1496 return nullptr; 1497 } 1498 1499 #if DISTRHO_PLUGIN_WANT_STATE 1500 if (worker == nullptr) 1501 { 1502 d_stderr("Worker feature missing, cannot continue!"); 1503 return nullptr; 1504 } 1505 #endif 1506 1507 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 1508 mod_license_check(features, DISTRHO_PLUGIN_URI); 1509 #endif 1510 1511 d_nextBufferSize = 0; 1512 bool usingNominal = false; 1513 1514 for (int i=0; options[i].key != 0; ++i) 1515 { 1516 if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength)) 1517 { 1518 if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int)) 1519 { 1520 d_nextBufferSize = *(const int*)options[i].value; 1521 usingNominal = true; 1522 } 1523 else 1524 { 1525 d_stderr("Host provides nominalBlockLength but has wrong value type"); 1526 } 1527 break; 1528 } 1529 1530 if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength)) 1531 { 1532 if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int)) 1533 d_nextBufferSize = *(const int*)options[i].value; 1534 else 1535 d_stderr("Host provides maxBlockLength but has wrong value type"); 1536 1537 // no break, continue in case host supports nominalBlockLength 1538 } 1539 } 1540 1541 if (d_nextBufferSize == 0) 1542 { 1543 d_stderr("Host does not provide nominalBlockLength or maxBlockLength options"); 1544 d_nextBufferSize = 2048; 1545 } 1546 1547 d_nextSampleRate = sampleRate; 1548 d_nextBundlePath = bundlePath; 1549 d_nextCanRequestParameterValueChanges = ctrlInPortChangeReq != nullptr; 1550 1551 if (std::getenv("RUNNING_UNDER_LV2LINT") != nullptr) 1552 d_nextPluginIsDummy = true; 1553 1554 return new PluginLv2(sampleRate, uridMap, worker, ctrlInPortChangeReq, usingNominal); 1555 } 1556 1557 #define instancePtr ((PluginLv2*)instance) 1558 1559 static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation) 1560 { 1561 instancePtr->lv2_connect_port(port, dataLocation); 1562 } 1563 1564 static void lv2_activate(LV2_Handle instance) 1565 { 1566 instancePtr->lv2_activate(); 1567 } 1568 1569 static void lv2_run(LV2_Handle instance, uint32_t sampleCount) 1570 { 1571 instancePtr->lv2_run(sampleCount); 1572 } 1573 1574 static void lv2_deactivate(LV2_Handle instance) 1575 { 1576 instancePtr->lv2_deactivate(); 1577 } 1578 1579 static void lv2_cleanup(LV2_Handle instance) 1580 { 1581 delete instancePtr; 1582 } 1583 1584 // ----------------------------------------------------------------------- 1585 1586 static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options) 1587 { 1588 return instancePtr->lv2_get_options(options); 1589 } 1590 1591 static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* options) 1592 { 1593 return instancePtr->lv2_set_options(options); 1594 } 1595 1596 // ----------------------------------------------------------------------- 1597 1598 #if DISTRHO_PLUGIN_WANT_PROGRAMS 1599 static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index) 1600 { 1601 return instancePtr->lv2_get_program(index); 1602 } 1603 1604 static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t program) 1605 { 1606 instancePtr->lv2_select_program(bank, program); 1607 } 1608 #endif 1609 1610 // ----------------------------------------------------------------------- 1611 1612 #if DISTRHO_PLUGIN_WANT_STATE 1613 static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t, const LV2_Feature* const* const features) 1614 { 1615 return instancePtr->lv2_save(store, handle, features); 1616 } 1617 1618 static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t, const LV2_Feature* const* const features) 1619 { 1620 return instancePtr->lv2_restore(retrieve, handle, features); 1621 } 1622 1623 LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function, LV2_Worker_Respond_Handle, uint32_t, const void* data) 1624 { 1625 return instancePtr->lv2_work(data); 1626 } 1627 1628 LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const void* body) 1629 { 1630 return instancePtr->lv2_work_response(size, body); 1631 } 1632 #endif 1633 1634 // ----------------------------------------------------------------------- 1635 1636 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1637 static void* lv2_get_instance_pointer(LV2_Handle instance) 1638 { 1639 return instancePtr->lv2_get_instance_pointer(); 1640 } 1641 #endif 1642 1643 // ----------------------------------------------------------------------- 1644 1645 static const void* lv2_extension_data(const char* uri) 1646 { 1647 static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; 1648 1649 if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) 1650 return &options; 1651 1652 #if DISTRHO_PLUGIN_WANT_PROGRAMS 1653 static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program }; 1654 1655 if (std::strcmp(uri, LV2_PROGRAMS__Interface) == 0) 1656 return &programs; 1657 #endif 1658 1659 #if DISTRHO_PLUGIN_WANT_STATE 1660 static const LV2_State_Interface state = { lv2_save, lv2_restore }; 1661 static const LV2_Worker_Interface worker = { lv2_work, lv2_work_response, nullptr }; 1662 1663 if (std::strcmp(uri, LV2_STATE__interface) == 0) 1664 return &state; 1665 if (std::strcmp(uri, LV2_WORKER__interface) == 0) 1666 return &worker; 1667 #endif 1668 1669 #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1670 struct LV2_DirectAccess_Interface { 1671 void* (*get_instance_pointer)(LV2_Handle handle); 1672 }; 1673 1674 static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer }; 1675 1676 if (std::strcmp(uri, DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access") == 0) 1677 return &directaccess; 1678 #endif 1679 1680 #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD 1681 return mod_license_interface(uri); 1682 #else 1683 return nullptr; 1684 #endif 1685 } 1686 1687 #undef instancePtr 1688 1689 // ----------------------------------------------------------------------- 1690 1691 static const LV2_Descriptor sLv2Descriptor = { 1692 DISTRHO_PLUGIN_URI, 1693 lv2_instantiate, 1694 lv2_connect_port, 1695 lv2_activate, 1696 lv2_run, 1697 lv2_deactivate, 1698 lv2_cleanup, 1699 lv2_extension_data 1700 }; 1701 1702 // ----------------------------------------------------------------------- 1703 1704 END_NAMESPACE_DISTRHO 1705 1706 DISTRHO_PLUGIN_EXPORT 1707 const LV2_Descriptor* lv2_descriptor(uint32_t index) 1708 { 1709 USE_NAMESPACE_DISTRHO 1710 return (index == 0) ? &sLv2Descriptor : nullptr; 1711 } 1712 1713 // -----------------------------------------------------------------------