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.
19 #error This file is not supposed to be built with wine!
21 #ifndef CARLA_PLUGIN_SYNTH
22 #error CARLA_PLUGIN_SYNTH undefined
25 #ifndef CARLA_VST_SHELL
26 #ifndef CARLA_PLUGIN_PATCHBAY
27 #error CARLA_PLUGIN_PATCHBAY undefined
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
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');
55 static const int32_t kShellUniqueID
= CCONST('C', 'r', 'l', 'F');
58 static const int32_t kNumParameters
= 100;
61 static const bool kIsUsingUILauncher
= isUsingUILauncher();
63 // --------------------------------------------------------------------------------------------------------------------
64 // Carla Internal Plugin API exposed as VST plugin
69 static const uint32_t kMaxMidiEvents
= 512;
71 NativePlugin(AEffect
* const effect
, const NativePluginDescriptor
* desc
)
76 fBufferSize(d_lastBufferSize
),
77 fSampleRate(d_lastSampleRate
),
83 fHostType(kHostTypeNull
),
88 fHost
.uiName
= carla_strdup("CarlaVST");
91 std::memset(fProgramName
, 0, sizeof(fProgramName
));
92 std::strcpy(fProgramName
, "Default");
98 File curExe
= File::getSpecialLocation(File::currentExecutableFile
).getLinkedTarget();
99 File resDir
= curExe
.getSiblingFile("resources");
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");
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
;
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
;
141 fVstRect
.right
= static_cast<int16_t>(fDescriptor
->ui_width
);
142 fVstRect
.bottom
= static_cast<int16_t>(fDescriptor
->ui_height
);
152 // host has not de-activated the plugin yet, nasty!
155 if (fDescriptor
->deactivate
!= nullptr)
156 fDescriptor
->deactivate(fHandle
);
159 if (fDescriptor
->cleanup
!= nullptr && fHandle
!= nullptr)
160 fDescriptor
->cleanup(fHandle
);
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;
185 if (fDescriptor
->instantiate
== nullptr || fDescriptor
->process
== nullptr)
187 carla_stderr("Plugin is missing something...");
191 fHandle
= fDescriptor
->instantiate(&fHost
);
192 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
194 carla_zeroStructs(fMidiEvents
, kMaxMidiEvents
);
195 carla_zeroStruct(fTimeInfo
);
200 const NativePluginDescriptor
* getDescriptor() const noexcept
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);
219 case effSetProgramName
:
220 if (char* const programName
= (char*)ptr
)
222 std::strncpy(fProgramName
, programName
, 32);
227 case effGetProgramName
:
228 if (char* const programName
= (char*)ptr
)
230 std::strncpy(programName
, fProgramName
, 23);
231 programName
[23] = '\0';
236 case effGetProgramNameIndexed
:
237 if (char* const programName
= (char*)ptr
)
239 std::strncpy(programName
, fProgramName
, 23);
240 programName
[23] = '\0';
245 case effGetParamDisplay
:
246 CARLA_SAFE_ASSERT_RETURN(index
>= 0, 0);
247 #ifndef CARLA_VST_SHELL
248 CARLA_SAFE_ASSERT_RETURN(index
< kNumParameters
, 0);
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
))
280 std::strncpy(cptr
, scalePoint
.label
, 23);
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
: "");
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
: "");
306 case effGetParamName
:
307 CARLA_SAFE_ASSERT_RETURN(index
>= 0, 0);
308 #ifndef CARLA_VST_SHELL
309 CARLA_SAFE_ASSERT_RETURN(index
< kNumParameters
, 0);
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);
326 case effSetSampleRate
:
327 CARLA_SAFE_ASSERT_RETURN(opt
> 0.0f
, 0);
329 if (carla_isEqual(fSampleRate
, static_cast<double>(opt
)))
334 if (fDescriptor
->dispatcher
!= nullptr)
335 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED
, 0, 0, nullptr, opt
);
338 case effSetBlockSize
:
339 CARLA_SAFE_ASSERT_RETURN(value
> 0, 0);
341 if (fBufferSize
== static_cast<uint32_t>(value
))
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
);
350 case effMainsChanged
:
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
);
391 CARLA_SAFE_ASSERT_BREAK(fIsActive
);
393 if (fDescriptor
->deactivate
!= nullptr)
394 fDescriptor
->deactivate(fHandle
);
401 *(VstRect
**)ptr
= &fVstRect
;
406 if (fDescriptor
->ui_show
!= nullptr)
408 if (kIsUsingUILauncher
)
410 destoryUILauncher(fUiLauncher
);
411 fUiLauncher
= createUILauncher((uintptr_t)ptr
, fDescriptor
, fHandle
);
412 getUILauncherSize(fUiLauncher
, &fVstRect
);
417 std::snprintf(strBuf
, 0xff, P_INTPTR
, (intptr_t)ptr
);
420 // set CARLA_PLUGIN_EMBED_WINID for external process
421 carla_setenv("CARLA_PLUGIN_EMBED_WINID", strBuf
);
424 fDescriptor
->ui_show(fHandle
, true);
426 // reset CARLA_PLUGIN_EMBED_WINID just in case
427 carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0");
434 if (fDescriptor
->ui_show
!= nullptr)
436 if (kIsUsingUILauncher
)
438 destoryUILauncher(fUiLauncher
);
439 fUiLauncher
= nullptr;
443 fDescriptor
->ui_show(fHandle
, false);
450 if (fUiLauncher
!= nullptr)
451 idleUILauncher(fUiLauncher
);
452 if (fDescriptor
->ui_idle
!= nullptr)
453 fDescriptor
->ui_idle(fHandle
);
457 if (ptr
== nullptr || fDescriptor
->get_state
== nullptr)
460 if (fStateChunk
!= nullptr)
461 std::free(fStateChunk
);
463 fStateChunk
= fDescriptor
->get_state(fHandle
);
465 if (fStateChunk
== nullptr)
468 ret
= static_cast<intptr_t>(std::strlen(fStateChunk
)+1);
469 *(void**)ptr
= fStateChunk
;
473 if (value
<= 0 || fDescriptor
->set_state
== nullptr)
478 if (const char* const state
= (const char*)ptr
)
480 fDescriptor
->set_state(fHandle
, state
);
485 case effProcessEvents
:
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)
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)
503 if (vstMidiEvent
->type
!= kVstMidiType
|| vstMidiEvent
->deltaFrames
< 0)
505 if (fMidiEventCount
>= kMaxMidiEvents
)
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
]);
520 case effCanBeAutomated
:
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)
533 if (std::strcmp(canDo
, "sendVstEvents") == 0 || std::strcmp(canDo
, "sendVstMidiEvent") == 0)
535 if (fDescriptor
->midiOuts
== 0)
539 if (std::strcmp(canDo
, "receiveVstTimeInfo") == 0)
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,);
575 if (param
->hints
& NATIVE_PARAMETER_IS_BOOLEAN
)
577 realValue
= value
> 0.5f
? param
->ranges
.max
: param
->ranges
.min
;
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)
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
);
608 if (fDescriptor
->activate
!= nullptr)
609 fDescriptor
->activate(fHandle
);
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
;
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);
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
;
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
);
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
);
691 if (fMidiOutEvents
.numEvents
> 0)
692 hostCallback(audioMasterProcessEvents
, 0, 0, &fMidiOutEvents
, 0.0f
);
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
);
710 fMidiOutEvents
.numEvents
= 0;
713 VstMidiEvent
& vstMidiEvent(fMidiOutEvents
.mdata
[fMidiOutEvents
.numEvents
++]);
715 vstMidiEvent
.type
= kVstMidiType
;
716 vstMidiEvent
.byteSize
= kVstMidiEventSize
;
719 for (; i
<event
->size
; ++i
)
720 vstMidiEvent
.midiData
[i
] = static_cast<char>(event
->data
[i
]);
722 vstMidiEvent
.midiData
[i
] = 0;
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
)
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
765 const char* handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
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
));
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
:
792 case NATIVE_HOST_OPCODE_RELOAD_ALL
:
793 hostCallback(audioMasterUpdateDisplay
);
796 case NATIVE_HOST_OPCODE_HOST_IDLE
:
797 hostCallback(audioMasterIdle
);
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);
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
));
815 (void)ptr
; (void)opt
;
820 AEffect
* const fEffect
;
823 NativePluginHandle fHandle
;
824 NativeHostDescriptor fHost
;
825 const NativePluginDescriptor
* const fDescriptor
;
828 uint32_t fBufferSize
;
833 uint32_t fMidiEventCount
;
834 NativeMidiEvent fMidiEvents
[kMaxMidiEvents
];
835 char fProgramName
[32+1];
836 NativeTimeInfo fTimeInfo
;
840 CarlaUILauncher
* fUiLauncher
;
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
{
863 VstEvent
* data
[kMaxMidiEvents
];
864 VstMidiEvent mdata
[kMaxMidiEvents
];
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
);
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*/)
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
);
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
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)
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;
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";
1009 const char* const pluginLabel
= "carlarack";
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
;
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
;
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;
1042 effect->flags &= ~effFlagsIsSynth;
1044 #endif // CARLA_VST_SHELL
1046 #if CARLA_PLUGIN_SYNTH
1047 // override if requested
1048 effect
->flags
|= effFlagsIsSynth
;
1051 obj
->plugin
= new NativePlugin(effect
, pluginDesc
);
1057 if (VstObject
* const obj
= vstObjectPtr
)
1059 NativePlugin
* const plugin(obj
->plugin
);
1061 if (plugin
!= nullptr)
1063 obj
->plugin
= nullptr;
1068 /* This code invalidates the object created in VSTPluginMain
1069 * Probably not safe against all hosts */
1070 obj
->audioMaster
= nullptr;
1071 effect
->object
= nullptr;
1080 case effGetPlugCategory
:
1081 #ifdef CARLA_VST_SHELL
1084 #if CARLA_PLUGIN_SYNTH
1085 return kPlugCategSynth
;
1087 const NativePluginDescriptor
* const desc
= pluginPtr
->getDescriptor();
1088 return desc
->category
== NATIVE_PLUGIN_CATEGORY_SYNTH
? kPlugCategSynth
: kPlugCategEffect
;
1092 return kPlugCategShell
;
1093 #elif CARLA_PLUGIN_SYNTH
1094 return kPlugCategSynth
;
1096 return kPlugCategEffect
;
1099 case effGetEffectName
:
1100 if (char* const cptr
= (char*)ptr
)
1102 #if defined(CARLA_VST_SHELL)
1105 const NativePluginDescriptor
* const desc
= pluginPtr
->getDescriptor();
1106 #if CARLA_PLUGIN_SYNTH
1107 std::strncpy(cptr
, desc
->name
, 32);
1109 std::snprintf(cptr
, 32, "%s FX", desc
->name
);
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);
1126 std::strncpy(cptr
, "Carla-PatchbayFX", 32);
1129 # if CARLA_PLUGIN_SYNTH
1130 std::strncpy(cptr
, "Carla-Rack", 32);
1132 std::strncpy(cptr
, "Carla-RackFX", 32);
1139 case effGetVendorString
:
1140 if (char* const cptr
= (char*)ptr
)
1142 #ifdef CARLA_VST_SHELL
1145 const NativePluginDescriptor
* const desc
= pluginPtr
->getDescriptor();
1146 std::strncpy(cptr
, desc
->maker
, 32);
1150 std::strncpy(cptr
, "falkTX", 32);
1155 case effGetProductString
:
1156 if (char* const cptr
= (char*)ptr
)
1158 #if defined(CARLA_VST_SHELL)
1161 const NativePluginDescriptor
* const desc
= pluginPtr
->getDescriptor();
1162 #if CARLA_PLUGIN_SYNTH
1163 std::strncpy(cptr
, desc
->label
, 32);
1165 std::snprintf(cptr
, 32, "%sFX", desc
->label
);
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);
1182 std::strncpy(cptr
, "CarlaPatchbayFX", 32);
1185 # if CARLA_PLUGIN_SYNTH
1186 std::strncpy(cptr
, "CarlaRack", 32);
1188 std::strncpy(cptr
, "CarlaRackFX", 32);
1195 case effGetVendorVersion
:
1196 return CARLA_VERSION_HEX
;
1198 case effGetVstVersion
:
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());
1212 const uint index2
= static_cast<uint
>(effect
->uniqueID
- kShellUniqueID
);
1214 if (index2
>= plm
.descs
.count())
1216 effect
->uniqueID
= kShellUniqueID
;
1220 const NativePluginDescriptor
* const desc
= plm
.descs
.getAt(index2
, nullptr);
1221 CARLA_SAFE_ASSERT_RETURN(desc
!= nullptr, 0);
1225 if (desc
->midiIns
> 1 || desc
->midiOuts
> 1)
1228 #if CARLA_PLUGIN_SYNTH
1229 std::strncpy(cptr
, desc
->label
, 32);
1231 std::snprintf(cptr
, 32, "%sFX", desc
->label
);
1234 return effect
->uniqueID
;
1240 // handle advanced opcodes
1242 return pluginPtr
->vst_dispatcher(opcode
, index
, value
, ptr
, opt
);
1247 float vst_getParameterCallback(AEffect
* effect
, int32_t index
)
1250 return pluginPtr
->vst_getParameter(index
);
1254 void vst_setParameterCallback(AEffect
* effect
, int32_t index
, float value
)
1257 pluginPtr
->vst_setParameter(index
, value
);
1260 void vst_processCallback(AEffect
* effect
, float** inputs
, float** outputs
, int32_t sampleFrames
)
1263 pluginPtr
->vst_processReplacing(inputs
, outputs
, sampleFrames
);
1266 void vst_processReplacingCallback(AEffect
* effect
, float** inputs
, float** outputs
, int32_t sampleFrames
)
1269 pluginPtr
->vst_processReplacing(inputs
, outputs
, sampleFrames
);
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
);
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;
1296 effect
->uniqueID
= kBaseUniqueID
+3;
1299 # if CARLA_PLUGIN_SYNTH
1300 effect
->uniqueID
= kBaseUniqueID
+2;
1302 effect
->uniqueID
= kBaseUniqueID
+1;
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;
1320 effect
->numInputs
= 2;
1321 effect
->numOutputs
= 2;
1326 effect
->flags
|= effFlagsCanReplacing
;
1327 effect
->flags
|= effFlagsProgramChunks
;
1328 #ifndef CARLA_VST_SHELL
1329 effect
->flags
|= effFlagsHasEditor
;
1331 #if CARLA_PLUGIN_SYNTH
1332 effect
->flags
|= effFlagsIsSynth
;
1338 (void)kBaseUniqueID
;
1341 // -----------------------------------------------------------------------