Fix potential wrong-over-optimization in math utilities
[carla.git] / source / plugin / carla-vst.cpp
blob2cb278ba482c1a27b995eb731b620a399a6482ae
1 /*
2 * Carla Native Plugins
3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifdef __WINE__
19 #error This file is not supposed to be built with wine!
20 #endif
21 #ifndef CARLA_PLUGIN_SYNTH
22 #error CARLA_PLUGIN_SYNTH undefined
23 #endif
25 #ifndef CARLA_VST_SHELL
26 #ifndef CARLA_PLUGIN_PATCHBAY
27 #error CARLA_PLUGIN_PATCHBAY undefined
28 #endif
29 #if defined(CARLA_PLUGIN_64CH) || defined(CARLA_PLUGIN_32CH) || defined(CARLA_PLUGIN_16CH)
30 #if ! CARLA_PLUGIN_SYNTH
31 #error CARLA_PLUGIN_16/32/64CH requires CARLA_PLUGIN_SYNTH
32 #endif
33 #endif
34 #endif
36 #define CARLA_NATIVE_PLUGIN_VST
37 #include "carla-base.cpp"
38 #include "carla-vst.hpp"
40 #include "water/files/File.h"
42 #include "CarlaMathUtils.hpp"
43 #include "CarlaVst2Utils.hpp"
45 static uint32_t d_lastBufferSize = 0;
46 static double d_lastSampleRate = 0.0;
48 static const int32_t kBaseUniqueID = CCONST('C', 'r', 'l', 'a');
49 static const int32_t kVstMidiEventSize = static_cast<int32_t>(sizeof(VstMidiEvent));
51 #ifdef CARLA_VST_SHELL
52 # if CARLA_PLUGIN_SYNTH
53 static const int32_t kShellUniqueID = CCONST('C', 'r', 'l', 's');
54 # else
55 static const int32_t kShellUniqueID = CCONST('C', 'r', 'l', 'F');
56 # endif
57 #else
58 static const int32_t kNumParameters = 100;
59 #endif
61 static const bool kIsUsingUILauncher = isUsingUILauncher();
63 // --------------------------------------------------------------------------------------------------------------------
64 // Carla Internal Plugin API exposed as VST plugin
66 class NativePlugin
68 public:
69 static const uint32_t kMaxMidiEvents = 512;
71 NativePlugin(AEffect* const effect, const NativePluginDescriptor* desc)
72 : fEffect(effect),
73 fHandle(nullptr),
74 fHost(),
75 fDescriptor(desc),
76 fBufferSize(d_lastBufferSize),
77 fSampleRate(d_lastSampleRate),
78 fIsActive(false),
79 fMidiEventCount(0),
80 fTimeInfo(),
81 fVstRect(),
82 fUiLauncher(nullptr),
83 fHostType(kHostTypeNull),
84 fMidiOutEvents(),
85 fStateChunk(nullptr)
87 fHost.handle = this;
88 fHost.uiName = carla_strdup("CarlaVST");
89 fHost.uiParentId = 0;
91 std::memset(fProgramName, 0, sizeof(fProgramName));
92 std::strcpy(fProgramName, "Default");
94 // find resource dir
95 using water::File;
96 using water::String;
98 File curExe = File::getSpecialLocation(File::currentExecutableFile).getLinkedTarget();
99 File resDir = curExe.getSiblingFile("resources");
101 #ifndef CARLA_OS_MAC
102 // FIXME: proper fallback path for other OSes
103 if (! resDir.exists())
104 resDir = File("/usr/local/share/carla/resources");
105 if (! resDir.exists())
106 resDir = File("/usr/share/carla/resources");
107 #endif
109 // find host type
110 const String hostFilename(File::getSpecialLocation(File::hostApplicationPath).getFileName());
112 /**/ if (hostFilename.startsWith("ardour"))
113 fHostType = kHostTypeArdour;
114 else if (hostFilename.startsWith("Bitwig"))
115 fHostType = kHostTypeBitwig;
117 fHost.resourceDir = carla_strdup(resDir.getFullPathName().toRawUTF8());
119 fHost.get_buffer_size = host_get_buffer_size;
120 fHost.get_sample_rate = host_get_sample_rate;
121 fHost.is_offline = host_is_offline;
122 fHost.get_time_info = host_get_time_info;
123 fHost.write_midi_event = host_write_midi_event;
124 fHost.ui_parameter_changed = host_ui_parameter_changed;
125 fHost.ui_custom_data_changed = host_ui_custom_data_changed;
126 fHost.ui_closed = host_ui_closed;
127 fHost.ui_open_file = host_ui_open_file;
128 fHost.ui_save_file = host_ui_save_file;
129 fHost.dispatcher = host_dispatcher;
131 fVstRect.top = 0;
132 fVstRect.left = 0;
134 if (kIsUsingUILauncher || (fDescriptor->hints & NATIVE_PLUGIN_USES_UI_SIZE) == 0x0)
136 fVstRect.right = ui_launcher_res::carla_uiWidth;
137 fVstRect.bottom = ui_launcher_res::carla_uiHeight;
139 else
141 fVstRect.right = static_cast<int16_t>(fDescriptor->ui_width);
142 fVstRect.bottom = static_cast<int16_t>(fDescriptor->ui_height);
145 init();
148 ~NativePlugin()
150 if (fIsActive)
152 // host has not de-activated the plugin yet, nasty!
153 fIsActive = false;
155 if (fDescriptor->deactivate != nullptr)
156 fDescriptor->deactivate(fHandle);
159 if (fDescriptor->cleanup != nullptr && fHandle != nullptr)
160 fDescriptor->cleanup(fHandle);
162 fHandle = nullptr;
164 if (fStateChunk != nullptr)
166 std::free(fStateChunk);
167 fStateChunk = nullptr;
170 if (fHost.uiName != nullptr)
172 delete[] fHost.uiName;
173 fHost.uiName = nullptr;
176 if (fHost.resourceDir != nullptr)
178 delete[] fHost.resourceDir;
179 fHost.resourceDir = nullptr;
183 bool init()
185 if (fDescriptor->instantiate == nullptr || fDescriptor->process == nullptr)
187 carla_stderr("Plugin is missing something...");
188 return false;
191 fHandle = fDescriptor->instantiate(&fHost);
192 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
194 carla_zeroStructs(fMidiEvents, kMaxMidiEvents);
195 carla_zeroStruct(fTimeInfo);
197 return true;
200 const NativePluginDescriptor* getDescriptor() const noexcept
202 return fDescriptor;
205 // -------------------------------------------------------------------
207 intptr_t vst_dispatcher(const int32_t opcode,
208 const int32_t index, const intptr_t value, void* const ptr, const float opt)
210 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0);
212 intptr_t ret = 0;
214 switch (opcode)
216 case effGetProgram:
217 return 0;
219 case effSetProgramName:
220 if (char* const programName = (char*)ptr)
222 std::strncpy(fProgramName, programName, 32);
223 return 1;
225 break;
227 case effGetProgramName:
228 if (char* const programName = (char*)ptr)
230 std::strncpy(programName, fProgramName, 23);
231 programName[23] = '\0';
232 return 1;
234 break;
236 case effGetProgramNameIndexed:
237 if (char* const programName = (char*)ptr)
239 std::strncpy(programName, fProgramName, 23);
240 programName[23] = '\0';
241 return 1;
243 break;
245 case effGetParamDisplay:
246 CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
247 #ifndef CARLA_VST_SHELL
248 CARLA_SAFE_ASSERT_RETURN(index < kNumParameters, 0);
249 #endif
251 if (char* const cptr = (char*)ptr)
253 const uint32_t uindex = static_cast<uint32_t>(index);
254 CARLA_SAFE_ASSERT_RETURN(uindex < fDescriptor->paramIns, 0);
256 const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, uindex);
257 CARLA_SAFE_ASSERT_RETURN(param != nullptr, 0);
259 float paramValue = fDescriptor->get_parameter_value(fHandle, uindex);
261 if (param->hints & NATIVE_PARAMETER_IS_BOOLEAN)
263 const NativeParameterRanges& ranges(param->ranges);
264 const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f;
266 paramValue = paramValue > midRange ? ranges.max : ranges.min;
268 else if (param->hints & NATIVE_PARAMETER_IS_INTEGER)
270 paramValue = std::round(paramValue);
273 for (uint32_t i = 0; i < param->scalePointCount; ++i)
275 const NativeParameterScalePoint& scalePoint(param->scalePoints[uindex]);
277 if (carla_isNotEqual(paramValue, scalePoint.value))
278 continue;
280 std::strncpy(cptr, scalePoint.label, 23);
281 cptr[23] = '\0';
282 return 1;
285 if (param->hints & NATIVE_PARAMETER_IS_INTEGER)
287 std::snprintf(cptr, 23, "%d%s%s",
288 static_cast<int>(paramValue),
289 param->unit != nullptr && param->unit[0] != '\0' ? " " : "",
290 param->unit != nullptr && param->unit[0] != '\0' ? param->unit : "");
291 cptr[23] = '\0';
293 else
295 std::snprintf(cptr, 23, "%.12g%s%s",
296 static_cast<double>(paramValue),
297 param->unit != nullptr && param->unit[0] != '\0' ? " " : "",
298 param->unit != nullptr && param->unit[0] != '\0' ? param->unit : "");
299 cptr[23] = '\0';
302 return 1;
304 break;
306 case effGetParamName:
307 CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
308 #ifndef CARLA_VST_SHELL
309 CARLA_SAFE_ASSERT_RETURN(index < kNumParameters, 0);
310 #endif
312 if (char* const cptr = (char*)ptr)
314 const uint32_t uindex = static_cast<uint32_t>(index);
315 CARLA_SAFE_ASSERT_RETURN(uindex < fDescriptor->paramIns, 0);
317 const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, uindex);
318 CARLA_SAFE_ASSERT_RETURN(param != nullptr, 0);
320 std::strncpy(cptr, param->name, 15);
321 cptr[15] = '\0';
322 return 1;
324 return 0;
326 case effSetSampleRate:
327 CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
329 if (carla_isEqual(fSampleRate, static_cast<double>(opt)))
330 return 0;
332 fSampleRate = opt;
334 if (fDescriptor->dispatcher != nullptr)
335 fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, opt);
336 break;
338 case effSetBlockSize:
339 CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
341 if (fBufferSize == static_cast<uint32_t>(value))
342 return 0;
344 fBufferSize = static_cast<uint32_t>(value);
346 if (fDescriptor->dispatcher != nullptr)
347 fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, value, nullptr, 0.0f);
348 break;
350 case effMainsChanged:
351 if (value != 0)
353 fMidiEventCount = 0;
354 carla_zeroStruct(fTimeInfo);
356 // tell host we want MIDI events
357 if (fDescriptor->midiIns > 0)
358 hostCallback(audioMasterWantMidi);
360 // deactivate for possible changes
361 if (fDescriptor->deactivate != nullptr && fIsActive)
362 fDescriptor->deactivate(fHandle);
364 // check if something changed
365 const uint32_t bufferSize = static_cast<uint32_t>(hostCallback(audioMasterGetBlockSize));
366 const double sampleRate = static_cast<double>(hostCallback(audioMasterGetSampleRate));
368 if (bufferSize != 0 && fBufferSize != bufferSize && (fHostType != kHostTypeArdour || fBufferSize == 0))
370 fBufferSize = bufferSize;
372 if (fDescriptor->dispatcher != nullptr)
373 fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, bufferSize, nullptr, 0.0f);
376 if (carla_isNotZero(sampleRate) && carla_isNotEqual(fSampleRate, sampleRate))
378 fSampleRate = sampleRate;
380 if (fDescriptor->dispatcher != nullptr)
381 fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, (float)sampleRate);
384 if (fDescriptor->activate != nullptr)
385 fDescriptor->activate(fHandle);
387 fIsActive = true;
389 else
391 CARLA_SAFE_ASSERT_BREAK(fIsActive);
393 if (fDescriptor->deactivate != nullptr)
394 fDescriptor->deactivate(fHandle);
396 fIsActive = false;
398 break;
400 case effEditGetRect:
401 *(VstRect**)ptr = &fVstRect;
402 ret = 1;
403 break;
405 case effEditOpen:
406 if (fDescriptor->ui_show != nullptr)
408 if (kIsUsingUILauncher)
410 destoryUILauncher(fUiLauncher);
411 fUiLauncher = createUILauncher((uintptr_t)ptr, fDescriptor, fHandle);
412 getUILauncherSize(fUiLauncher, &fVstRect);
414 else
416 char strBuf[0xff+1];
417 std::snprintf(strBuf, 0xff, P_INTPTR, (intptr_t)ptr);
418 strBuf[0xff] = '\0';
420 // set CARLA_PLUGIN_EMBED_WINID for external process
421 carla_setenv("CARLA_PLUGIN_EMBED_WINID", strBuf);
423 // show UI now
424 fDescriptor->ui_show(fHandle, true);
426 // reset CARLA_PLUGIN_EMBED_WINID just in case
427 carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0");
429 ret = 1;
431 break;
433 case effEditClose:
434 if (fDescriptor->ui_show != nullptr)
436 if (kIsUsingUILauncher)
438 destoryUILauncher(fUiLauncher);
439 fUiLauncher = nullptr;
441 else
443 fDescriptor->ui_show(fHandle, false);
445 ret = 1;
447 break;
449 case effEditIdle:
450 if (fUiLauncher != nullptr)
451 idleUILauncher(fUiLauncher);
452 if (fDescriptor->ui_idle != nullptr)
453 fDescriptor->ui_idle(fHandle);
454 break;
456 case effGetChunk:
457 if (ptr == nullptr || fDescriptor->get_state == nullptr)
458 return 0;
460 if (fStateChunk != nullptr)
461 std::free(fStateChunk);
463 fStateChunk = fDescriptor->get_state(fHandle);
465 if (fStateChunk == nullptr)
466 return 0;
468 ret = static_cast<intptr_t>(std::strlen(fStateChunk)+1);
469 *(void**)ptr = fStateChunk;
470 break;
472 case effSetChunk:
473 if (value <= 0 || fDescriptor->set_state == nullptr)
474 return 0;
475 if (value == 1)
476 return 1;
478 if (const char* const state = (const char*)ptr)
480 fDescriptor->set_state(fHandle, state);
481 ret = 1;
483 break;
485 case effProcessEvents:
486 if (! fIsActive)
488 // host has not activated the plugin yet, nasty!
489 vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
492 if (const VstEvents* const events = (const VstEvents*)ptr)
494 if (events->numEvents == 0)
495 break;
497 for (int i=0, count=events->numEvents; i < count; ++i)
499 const VstMidiEvent* const vstMidiEvent((const VstMidiEvent*)events->events[i]);
501 if (vstMidiEvent == nullptr)
502 break;
503 if (vstMidiEvent->type != kVstMidiType || vstMidiEvent->deltaFrames < 0)
504 continue;
505 if (fMidiEventCount >= kMaxMidiEvents)
506 break;
508 const uint32_t j(fMidiEventCount++);
510 fMidiEvents[j].port = 0;
511 fMidiEvents[j].time = static_cast<uint32_t>(vstMidiEvent->deltaFrames);
512 fMidiEvents[j].size = 3;
514 for (uint32_t k=0; k<3; ++k)
515 fMidiEvents[j].data[k] = static_cast<uint8_t>(vstMidiEvent->midiData[k]);
518 break;
520 case effCanBeAutomated:
521 ret = 1;
522 break;
524 case effCanDo:
525 if (const char* const canDo = (const char*)ptr)
527 if (std::strcmp(canDo, "receiveVstEvents") == 0 || std::strcmp(canDo, "receiveVstMidiEvent") == 0)
529 if (fDescriptor->midiIns == 0)
530 return -1;
531 return 1;
533 if (std::strcmp(canDo, "sendVstEvents") == 0 || std::strcmp(canDo, "sendVstMidiEvent") == 0)
535 if (fDescriptor->midiOuts == 0)
536 return -1;
537 return 1;
539 if (std::strcmp(canDo, "receiveVstTimeInfo") == 0)
540 return 1;
542 break;
545 return ret;
548 float vst_getParameter(const int32_t index)
550 CARLA_SAFE_ASSERT_RETURN(index >= 0, 0.0f);
552 const uint32_t uindex = static_cast<uint32_t>(index);
553 CARLA_SAFE_ASSERT_RETURN(uindex < fDescriptor->paramIns, 0.0f);
555 const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, uindex);
556 CARLA_SAFE_ASSERT_RETURN(param != nullptr, 0);
558 const float realValue = fDescriptor->get_parameter_value(fHandle, uindex);
560 return (realValue - param->ranges.min) / (param->ranges.max - param->ranges.min);
563 void vst_setParameter(const int32_t index, const float value)
565 CARLA_SAFE_ASSERT_RETURN(index >= 0,);
567 const uint32_t uindex = static_cast<uint32_t>(index);
568 CARLA_SAFE_ASSERT_RETURN(uindex < fDescriptor->paramIns,);
570 const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, uindex);
571 CARLA_SAFE_ASSERT_RETURN(param != nullptr,);
573 float realValue;
575 if (param->hints & NATIVE_PARAMETER_IS_BOOLEAN)
577 realValue = value > 0.5f ? param->ranges.max : param->ranges.min;
579 else
581 realValue = param->ranges.min + ((param->ranges.max - param->ranges.min) * value);
583 if (param->hints & NATIVE_PARAMETER_IS_INTEGER)
584 realValue = std::round(realValue);
587 fDescriptor->set_parameter_value(fHandle, uindex, realValue);
590 // FIXME for v3.0, use const for the input buffer
591 void vst_processReplacing(float** const inputs, float** const outputs, const int32_t sampleFrames)
593 if (sampleFrames <= 0)
594 return;
596 if (fHostType == kHostTypeBitwig && static_cast<int32_t>(fBufferSize) != sampleFrames)
598 // deactivate first if needed
599 if (fIsActive && fDescriptor->deactivate != nullptr)
600 fDescriptor->deactivate(fHandle);
602 fBufferSize = static_cast<uint32_t>(sampleFrames);
604 if (fDescriptor->dispatcher != nullptr)
605 fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, sampleFrames, nullptr, 0.0f);
607 // activate again
608 if (fDescriptor->activate != nullptr)
609 fDescriptor->activate(fHandle);
611 fIsActive = true;
614 if (! fIsActive)
616 // host has not activated the plugin yet, nasty!
617 vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
620 static const int kWantVstTimeFlags = kVstTransportPlaying|kVstPpqPosValid|kVstTempoValid|kVstTimeSigValid;
622 if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)hostCallback(audioMasterGetTime, 0, kWantVstTimeFlags))
624 fTimeInfo.frame = static_cast<uint64_t>(std::max(0.0, vstTimeInfo->samplePos));
625 fTimeInfo.playing = (vstTimeInfo->flags & kVstTransportPlaying);
626 fTimeInfo.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0);
628 // ticksPerBeat is not possible with VST
629 fTimeInfo.bbt.ticksPerBeat = 960.0;
631 if (vstTimeInfo->flags & kVstTempoValid)
632 fTimeInfo.bbt.beatsPerMinute = vstTimeInfo->tempo;
633 else
634 fTimeInfo.bbt.beatsPerMinute = 120.0;
636 if ((vstTimeInfo->flags & kVstPpqPosValid) != 0 && (vstTimeInfo->flags & kVstTimeSigValid) != 0)
638 const double ppqPos = std::abs(vstTimeInfo->ppqPos);
639 const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator;
640 const double barBeats = (std::fmod(ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigNumerator;
641 const double rest = std::fmod(barBeats, 1.0);
643 fTimeInfo.bbt.bar = static_cast<int32_t>(ppqPos) / ppqPerBar + 1;
644 fTimeInfo.bbt.beat = static_cast<int32_t>(barBeats - rest + 0.5) + 1;
645 fTimeInfo.bbt.tick = rest * fTimeInfo.bbt.ticksPerBeat;
646 fTimeInfo.bbt.beatsPerBar = static_cast<float>(vstTimeInfo->timeSigNumerator);
647 fTimeInfo.bbt.beatType = static_cast<float>(vstTimeInfo->timeSigDenominator);
649 if (vstTimeInfo->ppqPos < 0.0)
651 fTimeInfo.bbt.bar = std::max(1, fTimeInfo.bbt.bar-1);
652 fTimeInfo.bbt.beat = std::max(1, vstTimeInfo->timeSigNumerator - fTimeInfo.bbt.beat + 1);
653 fTimeInfo.bbt.tick = std::max(0.0, fTimeInfo.bbt.ticksPerBeat - fTimeInfo.bbt.tick - 1);
656 else
658 fTimeInfo.bbt.bar = 1;
659 fTimeInfo.bbt.beat = 1;
660 fTimeInfo.bbt.tick = 0.0;
661 fTimeInfo.bbt.beatsPerBar = 4.0f;
662 fTimeInfo.bbt.beatType = 4.0f;
665 #if 0
666 // for testing bad host values
667 static double last = -99999.0;
668 if (carla_isNotEqual(vstTimeInfo->samplePos, last))
670 last = vstTimeInfo->samplePos;
671 carla_stdout("time info %f %f %lu | %i %i",
672 vstTimeInfo->samplePos, vstTimeInfo->ppqPos, fTimeInfo.frame,
673 vstTimeInfo->timeSigNumerator, vstTimeInfo->timeSigDenominator);
675 #endif
677 fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat *
678 static_cast<double>(fTimeInfo.bbt.beatsPerBar) *
679 (fTimeInfo.bbt.bar - 1);
682 fMidiOutEvents.numEvents = 0;
684 if (fHandle != nullptr)
685 fDescriptor->process(fHandle,
686 inputs, outputs, static_cast<uint32_t>(sampleFrames),
687 fMidiEvents, fMidiEventCount);
689 fMidiEventCount = 0;
691 if (fMidiOutEvents.numEvents > 0)
692 hostCallback(audioMasterProcessEvents, 0, 0, &fMidiOutEvents, 0.0f);
695 protected:
696 // -------------------------------------------------------------------
698 bool handleWriteMidiEvent(const NativeMidiEvent* const event)
700 CARLA_SAFE_ASSERT_RETURN(fDescriptor->midiOuts > 0, false);
701 CARLA_SAFE_ASSERT_RETURN(event != nullptr, false);
702 CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false);
704 if (fMidiOutEvents.numEvents >= static_cast<int32_t>(kMaxMidiEvents))
706 // send current events
707 hostCallback(audioMasterProcessEvents, 0, 0, &fMidiOutEvents, 0.0f);
709 // clear
710 fMidiOutEvents.numEvents = 0;
713 VstMidiEvent& vstMidiEvent(fMidiOutEvents.mdata[fMidiOutEvents.numEvents++]);
715 vstMidiEvent.type = kVstMidiType;
716 vstMidiEvent.byteSize = kVstMidiEventSize;
718 uint8_t i=0;
719 for (; i<event->size; ++i)
720 vstMidiEvent.midiData[i] = static_cast<char>(event->data[i]);
721 for (; i<4; ++i)
722 vstMidiEvent.midiData[i] = 0;
724 return true;
727 void handleUiParameterChanged(const uint32_t index, const float value) const
729 const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, index);
730 CARLA_SAFE_ASSERT_RETURN(param != nullptr,);
732 const float normalizedValue = (value - param->ranges.min) / (param->ranges.max - param->ranges.min);
734 hostCallback(audioMasterAutomate, static_cast<int32_t>(index), 0, nullptr, normalizedValue);
737 void handleUiParameterTouch(const uint32_t index, const bool touch) const
739 hostCallback(touch ? audioMasterBeginEdit : audioMasterEndEdit, static_cast<int32_t>(index));
742 void handleUiResize(const int16_t width, const int16_t height)
744 if (kIsUsingUILauncher)
745 return;
746 fVstRect.right = width;
747 fVstRect.bottom = height;
748 hostCallback(audioMasterSizeWindow, width, height);
751 void handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const
755 void handleUiClosed()
759 const char* handleUiOpenFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
761 // TODO
762 return nullptr;
765 const char* handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
767 // TODO
768 return nullptr;
771 intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
773 carla_debug("NativePlugin::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)",
774 opcode, index, value, ptr, static_cast<double>(opt));
776 switch (opcode)
778 case NATIVE_HOST_OPCODE_NULL:
779 case NATIVE_HOST_OPCODE_UPDATE_PARAMETER:
780 case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM:
781 case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS:
782 case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
783 case NATIVE_HOST_OPCODE_UI_UNAVAILABLE:
784 case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN:
785 case NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY:
786 case NATIVE_HOST_OPCODE_REQUEST_IDLE:
787 case NATIVE_HOST_OPCODE_GET_FILE_PATH:
788 case NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA:
789 // nothing
790 break;
792 case NATIVE_HOST_OPCODE_RELOAD_ALL:
793 hostCallback(audioMasterUpdateDisplay);
794 break;
796 case NATIVE_HOST_OPCODE_HOST_IDLE:
797 hostCallback(audioMasterIdle);
798 break;
800 case NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER:
801 CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
802 handleUiParameterTouch(static_cast<uint32_t>(index), value != 0);
803 break;
805 case NATIVE_HOST_OPCODE_UI_RESIZE:
806 CARLA_SAFE_ASSERT_RETURN(index > 0 && index < INT16_MAX, 0);
807 CARLA_SAFE_ASSERT_RETURN(value > 0 && value < INT16_MAX, 0);
808 handleUiResize(static_cast<int16_t>(index), static_cast<int16_t>(value));
809 break;
812 // unused for now
813 return 0;
815 (void)ptr; (void)opt;
818 private:
819 // VST stuff
820 AEffect* const fEffect;
822 // Native data
823 NativePluginHandle fHandle;
824 NativeHostDescriptor fHost;
825 const NativePluginDescriptor* const fDescriptor;
827 // VST host data
828 uint32_t fBufferSize;
829 double fSampleRate;
831 // Temporary data
832 bool fIsActive;
833 uint32_t fMidiEventCount;
834 NativeMidiEvent fMidiEvents[kMaxMidiEvents];
835 char fProgramName[32+1];
836 NativeTimeInfo fTimeInfo;
837 VstRect fVstRect;
839 // UI button
840 CarlaUILauncher* fUiLauncher;
842 // Host data
843 enum HostType {
844 kHostTypeNull = 0,
845 kHostTypeArdour,
846 kHostTypeBitwig
848 HostType fHostType;
850 // host callback
851 intptr_t hostCallback(const int32_t opcode,
852 const int32_t index = 0,
853 const intptr_t value = 0,
854 void* const ptr = nullptr,
855 const float opt = 0.0f) const
857 return VSTAudioMaster(fEffect, opcode, index, value, ptr, opt);
860 struct FixedVstEvents {
861 int32_t numEvents;
862 intptr_t reserved;
863 VstEvent* data[kMaxMidiEvents];
864 VstMidiEvent mdata[kMaxMidiEvents];
866 FixedVstEvents()
867 : numEvents(0),
868 reserved(0)
870 for (uint32_t i=0; i<kMaxMidiEvents; ++i)
871 data[i] = (VstEvent*)&mdata[i];
872 carla_zeroStructs(mdata, kMaxMidiEvents);
875 CARLA_DECLARE_NON_COPYABLE(FixedVstEvents);
876 } fMidiOutEvents;
878 char* fStateChunk;
880 // -------------------------------------------------------------------
882 #define handlePtr ((NativePlugin*)handle)
884 static uint32_t host_get_buffer_size(NativeHostHandle handle)
886 return handlePtr->fBufferSize;
889 static double host_get_sample_rate(NativeHostHandle handle)
891 return handlePtr->fSampleRate;
894 static bool host_is_offline(NativeHostHandle /*handle*/)
896 // TODO
897 return false;
900 static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle)
902 return &(handlePtr->fTimeInfo);
905 static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event)
907 return handlePtr->handleWriteMidiEvent(event);
910 static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value)
912 handlePtr->handleUiParameterChanged(index, value);
915 static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value)
917 handlePtr->handleUiCustomDataChanged(key, value);
920 static void host_ui_closed(NativeHostHandle handle)
922 handlePtr->handleUiClosed();
925 static const char* host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
927 return handlePtr->handleUiOpenFile(isDir, title, filter);
930 static const char* host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
932 return handlePtr->handleUiSaveFile(isDir, title, filter);
935 static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
937 return handlePtr->handleDispatcher(opcode, index, value, ptr, opt);
940 #undef handlePtr
942 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePlugin)
945 // -----------------------------------------------------------------------
947 #define validObject effect != nullptr && effect->object != nullptr
948 #define validPlugin effect != nullptr && effect->object != nullptr && ((VstObject*)effect->object)->plugin != nullptr
949 #define vstObjectPtr (VstObject*)effect->object
950 #define pluginPtr (vstObjectPtr)->plugin
952 intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
954 // handle base opcodes
955 switch (opcode)
957 case effOpen:
958 if (VstObject* const obj = vstObjectPtr)
960 // this must always be valid
961 CARLA_SAFE_ASSERT_RETURN(obj->audioMaster != nullptr, 0);
963 // some hosts call effOpen twice
964 if (obj->plugin != nullptr)
965 return 1;
967 d_lastBufferSize = static_cast<uint32_t>(VSTAudioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f));
968 d_lastSampleRate = static_cast<double>(VSTAudioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f));
970 // some hosts are not ready at this point or return 0 buffersize/samplerate
971 if (d_lastBufferSize == 0)
972 d_lastBufferSize = 2048;
973 if (d_lastSampleRate <= 0.0)
974 d_lastSampleRate = 44100.0;
976 const NativePluginDescriptor* pluginDesc = nullptr;
977 PluginListManager& plm(PluginListManager::getInstance());
979 #ifdef CARLA_VST_SHELL
980 if (effect->uniqueID == 0)
981 effect->uniqueID = kShellUniqueID;
983 if (effect->uniqueID == kShellUniqueID)
985 // first open for discovery, nothing to do
986 effect->numParams = 0;
987 effect->numPrograms = 0;
988 effect->numInputs = 0;
989 effect->numOutputs = 0;
990 return 1;
993 const int32_t plugIndex = effect->uniqueID - kShellUniqueID - 1;
994 CARLA_SAFE_ASSERT_RETURN(plugIndex >= 0, 0);
996 pluginDesc = plm.descs.getAt(static_cast<size_t>(plugIndex), nullptr);
998 #else // CARLA_VST_SHELL
1000 # if defined(CARLA_PLUGIN_64CH)
1001 const char* const pluginLabel = "carlapatchbay64";
1002 # elif defined(CARLA_PLUGIN_32CH)
1003 const char* const pluginLabel = "carlapatchbay32";
1004 # elif defined(CARLA_PLUGIN_16CH)
1005 const char* const pluginLabel = "carlapatchbay16";
1006 # elif CARLA_PLUGIN_PATCHBAY
1007 const char* const pluginLabel = "carlapatchbay";
1008 # else
1009 const char* const pluginLabel = "carlarack";
1010 # endif
1012 for (LinkedList<const NativePluginDescriptor*>::Itenerator it = plm.descs.begin2(); it.valid(); it.next())
1014 const NativePluginDescriptor* const& tmpDesc(it.getValue(nullptr));
1015 CARLA_SAFE_ASSERT_CONTINUE(tmpDesc != nullptr);
1017 if (std::strcmp(tmpDesc->label, pluginLabel) == 0)
1019 pluginDesc = tmpDesc;
1020 break;
1023 #endif // CARLA_VST_SHELL
1025 CARLA_SAFE_ASSERT_RETURN(pluginDesc != nullptr, 0);
1027 #ifdef CARLA_VST_SHELL
1028 effect->numPrograms = 1;
1029 effect->numParams = static_cast<int>(pluginDesc->paramIns);
1030 effect->numInputs = static_cast<int>(pluginDesc->audioIns);
1031 effect->numOutputs = static_cast<int>(pluginDesc->audioOuts);
1033 if (pluginDesc->hints & NATIVE_PLUGIN_HAS_UI)
1034 effect->flags |= effFlagsHasEditor;
1035 else
1036 effect->flags &= ~effFlagsHasEditor;
1038 /* carla as plugin always has NATIVE_PLUGIN_IS_SYNTH set
1039 if (pluginDesc->hints & NATIVE_PLUGIN_IS_SYNTH)
1040 effect->flags |= effFlagsIsSynth;
1041 else
1042 effect->flags &= ~effFlagsIsSynth;
1044 #endif // CARLA_VST_SHELL
1046 #if CARLA_PLUGIN_SYNTH
1047 // override if requested
1048 effect->flags |= effFlagsIsSynth;
1049 #endif
1051 obj->plugin = new NativePlugin(effect, pluginDesc);
1052 return 1;
1054 return 0;
1056 case effClose:
1057 if (VstObject* const obj = vstObjectPtr)
1059 NativePlugin* const plugin(obj->plugin);
1061 if (plugin != nullptr)
1063 obj->plugin = nullptr;
1064 delete plugin;
1067 #if 0
1068 /* This code invalidates the object created in VSTPluginMain
1069 * Probably not safe against all hosts */
1070 obj->audioMaster = nullptr;
1071 effect->object = nullptr;
1072 delete obj;
1073 #endif
1075 return 1;
1077 //delete effect;
1078 return 0;
1080 case effGetPlugCategory:
1081 #ifdef CARLA_VST_SHELL
1082 if (validPlugin)
1084 #if CARLA_PLUGIN_SYNTH
1085 return kPlugCategSynth;
1086 #else
1087 const NativePluginDescriptor* const desc = pluginPtr->getDescriptor();
1088 return desc->category == NATIVE_PLUGIN_CATEGORY_SYNTH ? kPlugCategSynth : kPlugCategEffect;
1089 #endif
1092 return kPlugCategShell;
1093 #elif CARLA_PLUGIN_SYNTH
1094 return kPlugCategSynth;
1095 #else
1096 return kPlugCategEffect;
1097 #endif
1099 case effGetEffectName:
1100 if (char* const cptr = (char*)ptr)
1102 #if defined(CARLA_VST_SHELL)
1103 if (validPlugin)
1105 const NativePluginDescriptor* const desc = pluginPtr->getDescriptor();
1106 #if CARLA_PLUGIN_SYNTH
1107 std::strncpy(cptr, desc->name, 32);
1108 #else
1109 std::snprintf(cptr, 32, "%s FX", desc->name);
1110 #endif
1112 else
1114 std::strncpy(cptr, "Carla-VstShell", 32);
1116 #elif defined(CARLA_PLUGIN_64CH)
1117 std::strncpy(cptr, "Carla-Patchbay64", 32);
1118 #elif defined(CARLA_PLUGIN_32CH)
1119 std::strncpy(cptr, "Carla-Patchbay32", 32);
1120 #elif defined(CARLA_PLUGIN_16CH)
1121 std::strncpy(cptr, "Carla-Patchbay16", 32);
1122 #elif CARLA_PLUGIN_PATCHBAY
1123 # if CARLA_PLUGIN_SYNTH
1124 std::strncpy(cptr, "Carla-Patchbay", 32);
1125 # else
1126 std::strncpy(cptr, "Carla-PatchbayFX", 32);
1127 # endif
1128 #else // Rack mode
1129 # if CARLA_PLUGIN_SYNTH
1130 std::strncpy(cptr, "Carla-Rack", 32);
1131 # else
1132 std::strncpy(cptr, "Carla-RackFX", 32);
1133 # endif
1134 #endif
1135 return 1;
1137 return 0;
1139 case effGetVendorString:
1140 if (char* const cptr = (char*)ptr)
1142 #ifdef CARLA_VST_SHELL
1143 if (validPlugin)
1145 const NativePluginDescriptor* const desc = pluginPtr->getDescriptor();
1146 std::strncpy(cptr, desc->maker, 32);
1148 else
1149 #endif
1150 std::strncpy(cptr, "falkTX", 32);
1151 return 1;
1153 return 0;
1155 case effGetProductString:
1156 if (char* const cptr = (char*)ptr)
1158 #if defined(CARLA_VST_SHELL)
1159 if (validPlugin)
1161 const NativePluginDescriptor* const desc = pluginPtr->getDescriptor();
1162 #if CARLA_PLUGIN_SYNTH
1163 std::strncpy(cptr, desc->label, 32);
1164 #else
1165 std::snprintf(cptr, 32, "%sFX", desc->label);
1166 #endif
1168 else
1170 std::strncpy(cptr, "CarlaVstShell", 32);
1172 #elif defined(CARLA_PLUGIN_64CH)
1173 std::strncpy(cptr, "CarlaPatchbay64", 32);
1174 #elif defined(CARLA_PLUGIN_32CH)
1175 std::strncpy(cptr, "CarlaPatchbay32", 32);
1176 #elif defined(CARLA_PLUGIN_16CH)
1177 std::strncpy(cptr, "CarlaPatchbay16", 32);
1178 #elif CARLA_PLUGIN_PATCHBAY
1179 # if CARLA_PLUGIN_SYNTH
1180 std::strncpy(cptr, "CarlaPatchbay", 32);
1181 # else
1182 std::strncpy(cptr, "CarlaPatchbayFX", 32);
1183 # endif
1184 #else
1185 # if CARLA_PLUGIN_SYNTH
1186 std::strncpy(cptr, "CarlaRack", 32);
1187 # else
1188 std::strncpy(cptr, "CarlaRackFX", 32);
1189 # endif
1190 #endif
1191 return 1;
1193 return 0;
1195 case effGetVendorVersion:
1196 return CARLA_VERSION_HEX;
1198 case effGetVstVersion:
1199 return kVstVersion;
1201 #ifdef CARLA_VST_SHELL
1202 case effShellGetNextPlugin:
1203 if (char* const cptr = (char*)ptr)
1205 CARLA_SAFE_ASSERT_RETURN(effect != nullptr, 0);
1206 CARLA_SAFE_ASSERT_RETURN(effect->uniqueID >= kShellUniqueID, 0);
1208 PluginListManager& plm(PluginListManager::getInstance());
1210 for (;;)
1212 const uint index2 = static_cast<uint>(effect->uniqueID - kShellUniqueID);
1214 if (index2 >= plm.descs.count())
1216 effect->uniqueID = kShellUniqueID;
1217 return 0;
1220 const NativePluginDescriptor* const desc = plm.descs.getAt(index2, nullptr);
1221 CARLA_SAFE_ASSERT_RETURN(desc != nullptr, 0);
1223 ++effect->uniqueID;
1225 if (desc->midiIns > 1 || desc->midiOuts > 1)
1226 continue;
1228 #if CARLA_PLUGIN_SYNTH
1229 std::strncpy(cptr, desc->label, 32);
1230 #else
1231 std::snprintf(cptr, 32, "%sFX", desc->label);
1232 #endif
1234 return effect->uniqueID;
1237 #endif
1240 // handle advanced opcodes
1241 if (validPlugin)
1242 return pluginPtr->vst_dispatcher(opcode, index, value, ptr, opt);
1244 return 0;
1247 float vst_getParameterCallback(AEffect* effect, int32_t index)
1249 if (validPlugin)
1250 return pluginPtr->vst_getParameter(index);
1251 return 0.0f;
1254 void vst_setParameterCallback(AEffect* effect, int32_t index, float value)
1256 if (validPlugin)
1257 pluginPtr->vst_setParameter(index, value);
1260 void vst_processCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
1262 if (validPlugin)
1263 pluginPtr->vst_processReplacing(inputs, outputs, sampleFrames);
1266 void vst_processReplacingCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
1268 if (validPlugin)
1269 pluginPtr->vst_processReplacing(inputs, outputs, sampleFrames);
1272 #undef pluginPtr
1273 #undef validObject
1274 #undef validPlugin
1275 #undef vstObjectPtr
1277 // -----------------------------------------------------------------------
1279 const AEffect* VSTPluginMainInit(AEffect* const effect)
1281 #if defined(CARLA_VST_SHELL)
1282 if (const intptr_t uniqueID = VSTAudioMaster(effect, audioMasterCurrentId, 0, 0, nullptr, 0.0f))
1283 effect->uniqueID = static_cast<int>(uniqueID);
1284 else
1285 effect->uniqueID = kShellUniqueID;
1286 #elif defined(CARLA_PLUGIN_64CH)
1287 effect->uniqueID = kBaseUniqueID+7;
1288 #elif defined(CARLA_PLUGIN_32CH)
1289 effect->uniqueID = kBaseUniqueID+6;
1290 #elif defined(CARLA_PLUGIN_16CH)
1291 effect->uniqueID = kBaseUniqueID+5;
1292 #elif CARLA_PLUGIN_PATCHBAY
1293 # if CARLA_PLUGIN_SYNTH
1294 effect->uniqueID = kBaseUniqueID+4;
1295 # else
1296 effect->uniqueID = kBaseUniqueID+3;
1297 # endif
1298 #else
1299 # if CARLA_PLUGIN_SYNTH
1300 effect->uniqueID = kBaseUniqueID+2;
1301 # else
1302 effect->uniqueID = kBaseUniqueID+1;
1303 # endif
1304 #endif
1306 // plugin fields
1307 #ifndef CARLA_VST_SHELL
1308 effect->numParams = kNumParameters;
1309 effect->numPrograms = 1;
1310 # if defined(CARLA_PLUGIN_64CH)
1311 effect->numInputs = 64;
1312 effect->numOutputs = 64;
1313 # elif defined(CARLA_PLUGIN_32CH)
1314 effect->numInputs = 32;
1315 effect->numOutputs = 32;
1316 # elif defined(CARLA_PLUGIN_16CH)
1317 effect->numInputs = 16;
1318 effect->numOutputs = 16;
1319 # else
1320 effect->numInputs = 2;
1321 effect->numOutputs = 2;
1322 # endif
1323 #endif
1325 // plugin flags
1326 effect->flags |= effFlagsCanReplacing;
1327 effect->flags |= effFlagsProgramChunks;
1328 #ifndef CARLA_VST_SHELL
1329 effect->flags |= effFlagsHasEditor;
1330 #endif
1331 #if CARLA_PLUGIN_SYNTH
1332 effect->flags |= effFlagsIsSynth;
1333 #endif
1335 return effect;
1337 // may be unused
1338 (void)kBaseUniqueID;
1341 // -----------------------------------------------------------------------