26#if JUCE_PLUGINHOST_VST
29#undef PRAGMA_ALIGN_SUPPORTED
32#if ! JUCE_MINGW && ! JUCE_MSVC
36JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wzero-as-null-pointer-constant")
37JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
39#define VST_FORCE_DEPRECATED 0
40#define JUCE_VSTINTERFACE_H_INCLUDED 1
51#include <pluginterfaces/vst2.x/aeffect.h>
52#include <pluginterfaces/vst2.x/aeffectx.h>
55#include "juce_VSTCommon.h"
57JUCE_END_IGNORE_WARNINGS_GCC_LIKE
58JUCE_END_IGNORE_WARNINGS_MSVC
60JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
61JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4355)
63#include "juce_VSTMidiEventList.h"
67 #define WM_APPCOMMAND 0x0319
70 static void _fpreset() {}
71 static void _clearfp() {}
74#ifndef JUCE_VST_WRAPPER_LOAD_CUSTOM_MAIN
75 #define JUCE_VST_WRAPPER_LOAD_CUSTOM_MAIN
78#ifndef JUCE_VST_WRAPPER_INVOKE_MAIN
79#define JUCE_VST_WRAPPER_INVOKE_MAIN effect = module->moduleMain ((Vst2::audioMasterCallback) &audioMaster);
82#ifndef JUCE_VST_FALLBACK_HOST_NAME
83 #define JUCE_VST_FALLBACK_HOST_NAME "Juce VST Host"
161 #ifdef JUCE_LITTLE_ENDIAN
179 #elif JUCE_LINUX || JUCE_BSD || JUCE_IOS || JUCE_ANDROID
182 return (
double) micro.tv_usec * 1000.0;
186 return micro.lo * 1000.0;
226 #define VST_LOGGING 1
230 #define JUCE_VST_LOG(a) Logger::writeToLog(a);
232 #define JUCE_VST_LOG(a)
236#if JUCE_LINUX || JUCE_BSD
248 X11Symbols::getInstance()->xQueryTree (XWindowSystem::getInstance()->getDisplay(),
266 if (xml.
hasTagName (
"VSTParametersStructure"))
269 if (
const auto* x = xml.
getChildByName (
"VSTParametersStructure"))
282 Group* parent =
nullptr;
314 high = str.fromLastOccurrenceOf (
",",
false,
false).getFloatValue();
317 bool contains (
float f)
const noexcept
319 return (inclusiveLow ? (f >= low) : (f > low))
320 && (inclusiveHigh ? (f <= high) : (f < high));
326 bool inclusiveLow =
false;
327 bool inclusiveHigh =
false;
352 if (
auto param =
dynamic_cast<const Param*
> (item))
353 if (param->paramID == paramID)
356 if (
auto group =
dynamic_cast<const Group*
> (item))
385 for (
auto* item : xml.getChildIterator())
387 if (item->hasTagName (
"Param"))
parseParam (*item,
nullptr,
nullptr);
389 else if (item->hasTagName (
"Template"))
parseTemplate (*item);
390 else if (item->hasTagName (
"Group"))
parseGroup (*item,
nullptr);
396 auto param =
new Param();
410 param->shortNames.trim();
411 param->shortNames.removeEmptyStrings();
413 if (group !=
nullptr)
415 group->paramTree.add (param);
416 param->parent = group;
418 else if (temp !=
nullptr)
420 temp->params.add (param);
430 auto vt =
new ValueType();
439 for (
auto*
entryXml : item.getChildWithTagNameIterator (
"Entry"))
441 auto entry =
new Entry();
442 entry->name =
entryXml->getStringAttribute (
"name");
444 if (
entryXml->hasAttribute (
"value"))
446 entry->range.set (
entryXml->getStringAttribute (
"value"));
453 entry->range.inclusiveLow =
true;
454 entry->range.inclusiveHigh = (
curEntry == numEntries - 1);
457 vt->entries.add (entry);
468 for (
auto* param : item.getChildIterator())
474 auto group =
new Group();
498 for (
int i = 0; i < temp->params.size(); ++i)
500 auto param =
new Param();
501 group->paramTree.add (param);
503 param->parent = group;
504 param->paramID = evaluate (temp->params[i]->expr,
variables);
505 param->defaultValue = temp->params[i]->defaultValue;
506 param->label = temp->params[i]->label;
507 param->name = temp->params[i]->name;
508 param->numberOfStates = temp->params[i]->numberOfStates;
509 param->shortNames = temp->params[i]->shortNames;
510 param->type = temp->params[i]->type;
517 for (
auto*
subItem : item.getChildIterator())
532 if (v.contains (
"="))
534 names.
add (v.upToFirstOccurrenceOf (
"=",
false,
false));
535 vals.add (v.fromFirstOccurrenceOf (
"=",
false,
false).getIntValue());
539 for (
int i = 0; i < names.
size(); ++i)
543 const int idx =
expr.indexOfWholeWord (names[i]);
551 expr =
expr.retainCharacters (
"01234567890-+")
552 .replace (
"+",
" + ")
553 .replace (
"-",
" - ");
561 for (
const auto& s : tokens)
611 JUCE_VST_LOG (
"Attempting to load VST: " + file.getFullPathName());
630 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD || JUCE_IOS || JUCE_ANDROID
650 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD || JUCE_ANDROID
651 DynamicLibrary
module;
658 pluginName = file.getFileNameWithoutExtension();
660 module.open (file.getFullPathName());
691 eff->dispatcher (
eff, Vst2::effClose, 0, 0,
nullptr, 0);
697 DynamicLibrary
dll (
dllFile.getFullPathName());
731 if (file.hasFileExtension (
".vst"))
733 auto*
utf8 = file.getFullPathName().toRawUTF8();
765 pluginName = file.getFileNameWithoutExtension();
775 .getChildFile (
"Contents")
776 .getChildFile (
"Resources")
815 eff->dispatcher (
eff, Vst2::effClose, 0, 0,
nullptr, 0);
827JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
832 template <
typename T>
837 jassert (buffer.getNumChannels() <=
static_cast<int> (
pointers.capacity()));
840 std::copy (buffer.getArrayOfWritePointers(),
841 buffer.getArrayOfWritePointers() + buffer.getNumChannels(),
848 template <
typename>
struct Tag {};
864 VSTParameter (VSTPluginInstance& parent,
865 const String& paramName,
866 const Array<String>& shortParamNames,
867 float paramDefaultValue,
868 const String& paramLabel,
869 bool paramIsAutomatable,
870 bool paramIsDiscrete,
873 const StringArray& paramValueStrings,
874 const VSTXMLInfo::ValueType* paramValueType)
875 : pluginInstance (parent),
877 shortNames (shortParamNames),
878 defaultValue (paramDefaultValue),
880 automatable (paramIsAutomatable),
881 discrete (paramIsDiscrete),
882 numSteps (numParamSteps),
883 isSwitch (isBoolSwitch),
884 vstValueStrings (paramValueStrings),
885 valueType (paramValueType)
889 float getValue()
const override
891 if (
auto* effect = pluginInstance.vstEffect)
895 return effect->getParameter (effect, getParameterIndex());
901 void setValue (
float newValue)
override
903 if (
auto* effect = pluginInstance.vstEffect)
907 if (! approximatelyEqual (effect->getParameter (effect, getParameterIndex()), newValue))
908 effect->setParameter (effect, getParameterIndex(), newValue);
912 String getText (
float value,
int maximumStringLength)
const override
914 if (valueType !=
nullptr)
916 for (
auto& v : valueType->entries)
917 if (v->range.contains (value))
921 return Parameter::getText (value, maximumStringLength);
924 float getValueForText (
const String& text)
const override
926 if (valueType !=
nullptr)
928 for (
auto& v : valueType->entries)
930 return (v->range.high + v->range.low) / 2.0f;
933 return Parameter::getValueForText (text);
936 String getCurrentValueAsText()
const override
938 if (valueType !=
nullptr || ! vstValueStrings.isEmpty())
939 return getText (getValue(), 1024);
941 return pluginInstance.getTextForOpcode (getParameterIndex(), Vst2::effGetParamDisplay);
944 float getDefaultValue()
const override
949 String getName (
int maximumStringLength)
const override
952 return pluginInstance.getTextForOpcode (getParameterIndex(),
953 Vst2::effGetParamName);
955 if (name.length() <= maximumStringLength)
958 if (! shortNames.isEmpty())
960 for (
auto& n : shortNames)
961 if (n.length() <= maximumStringLength)
964 return shortNames.getLast();
970 String getLabel()
const override
972 return label.isEmpty() ? pluginInstance.getTextForOpcode (getParameterIndex(),
973 Vst2::effGetParamLabel)
977 bool isAutomatable()
const override
982 bool isDiscrete()
const override
987 bool isBoolean()
const override
992 int getNumSteps()
const override
997 StringArray getAllValueStrings()
const override
999 return vstValueStrings;
1002 String getParameterID()
const override
1004 return String (getParameterIndex());
1007 VSTPluginInstance& pluginInstance;
1010 const Array<String> shortNames;
1011 const float defaultValue;
1013 const bool automatable, discrete;
1015 const bool isSwitch;
1016 const StringArray vstValueStrings;
1017 const VSTXMLInfo::ValueType*
const valueType;
1030 if (
auto* xml =
vstModule->vstXml.get())
1031 xmlInfo.reset (VSTXMLInfo::createFor (*xml));
1033 refreshParameterList();
1039 void refreshParameterList()
override
1043 for (
int i = 0; i <
vstEffect->numParams; ++i)
1047 float defaultValue = 0;
1049 bool isAutomatable =
dispatch (Vst2::effCanBeAutomated, i, 0,
nullptr, 0) != 0;
1050 bool isDiscrete =
false;
1054 const VSTXMLInfo::ValueType* valueType =
nullptr;
1058 if (
auto* param =
xmlInfo->getParamForID (i,
nullptr))
1069 return first.length() - second.length();
1076 defaultValue = param->defaultValue;
1077 label = param->label;
1079 if (param->type ==
"switch")
1083 valueType = &
xmlInfo->switchValueType;
1087 valueType =
xmlInfo->getValueType (param->type);
1090 if (param->numberOfStates >= 2)
1092 numSteps = param->numberOfStates;
1094 if (valueType !=
nullptr)
1096 for (
auto* entry : valueType->entries)
1108 label, isAutomatable, isDiscrete, numSteps,
1118 callOnMessageThread ([
this] { cleanup(); });
1131 jassert (getActiveEditor() ==
nullptr);
1167 void fillInPluginDescription (PluginDescription& desc)
const override
1172 char buffer[512] = { 0 };
1173 dispatch (Vst2::effGetEffectName, 0, 0, buffer, 0);
1177 if (desc.descriptiveName.isEmpty())
1178 desc.descriptiveName = name;
1181 desc.fileOrIdentifier =
vstModule->file.getFullPathName();
1182 desc.uniqueId = desc.deprecatedUid =
getUID();
1183 desc.lastFileModTime =
vstModule->file.getLastModificationTime();
1185 desc.pluginFormatName =
"VST";
1186 desc.category = getCategory();
1189 char buffer[512] = { 0 };
1190 dispatch (Vst2::effGetVendorString, 0, 0, buffer, 0);
1194 desc.version = getVersion();
1195 desc.numInputChannels = getTotalNumInputChannels();
1196 desc.numOutputChannels = getTotalNumOutputChannels();
1230 dispatch (Vst2::effIdentify, 0, 0,
nullptr, 0);
1232 if (getSampleRate() > 0)
1233 dispatch (Vst2::effSetSampleRate, 0, 0,
nullptr, (
float) getSampleRate());
1235 if (getBlockSize() > 0)
1236 dispatch (Vst2::effSetBlockSize, 0,
jmax (32, getBlockSize()),
nullptr, 0);
1238 dispatch (Vst2::effOpen, 0, 0,
nullptr, 0);
1240 setRateAndBufferSizeDetails (getSampleRate(), getBlockSize());
1242 if (getNumPrograms() > 1)
1243 setCurrentProgram (0);
1245 dispatch (Vst2::effSetProgram, 0, 0,
nullptr, 0);
1247 for (
int i =
vstEffect->numInputs; --i >= 0;)
dispatch (Vst2::effConnectInput, i, 1,
nullptr, 0);
1248 for (
int i =
vstEffect->numOutputs; --i >= 0;)
dispatch (Vst2::effConnectOutput, i, 1,
nullptr, 0);
1255 setLatencySamples (
vstEffect->initialDelay);
1258 void getExtensions (ExtensionsVisitor& visitor)
const override
1262 explicit Extensions (
const VSTPluginInstance* instanceIn) : instance (instanceIn) {}
1264 AEffect* getAEffectPtr() const noexcept
override {
return reinterpret_cast<AEffect*
> (instance->vstEffect); }
1266 const VSTPluginInstance* instance =
nullptr;
1269 visitor.visitVSTClient (
Extensions {
this });
1274 const String getName()
const override
1278 char buffer[512] = { 0 };
1280 if (
dispatch (Vst2::effGetProductString, 0, 0, buffer, 0) != 0)
1302 double getTailLengthSeconds()
const override
1307 if ((
vstEffect->flags & Vst2::effFlagsNoSoundInStop) != 0)
1311 auto sampleRate = getSampleRate();
1320 if (
tailSize >= 0 && sampleRate > 0)
1321 return static_cast<double> (
tailSize) / sampleRate;
1327 bool producesMidi()
const override {
return pluginCanDo (
"sendVstMidiEvent") > 0; }
1328 bool supportsMPE()
const override {
return pluginCanDo (
"MPE") > 0; }
1330 Vst2::VstPlugCategory
getVstCategory()
const noexcept {
return (Vst2::VstPlugCategory)
dispatch (Vst2::effGetPlugCategory, 0, 0,
nullptr, 0); }
1334 int pluginCanDo (
const char* text)
const {
return (
int)
dispatch (Vst2::effCanDo, 0, 0, (
void*) text, 0); }
1346 SpeakerMappings::VstSpeakerConfigurationHolder
inArr (getChannelLayoutOfBus (
true, 0));
1347 SpeakerMappings::VstSpeakerConfigurationHolder
outArr (getChannelLayoutOfBus (
false, 0));
1358 | Vst2::kVstAutomationWriting
1359 | Vst2::kVstAutomationReading;
1372 incomingMidi.clear();
1374 dispatch (Vst2::effSetSampleRate, 0, 0,
nullptr, (
float) rate);
1377 if (supportsDoublePrecisionProcessing())
1380 : Vst2::kVstProcessPrecision32;
1409 dispatch (Vst2::effStartProcess, 0, 0,
nullptr, 0);
1411 setLatencySamples (
vstEffect->initialDelay);
1415 void releaseResources()
override
1419 dispatch (Vst2::effStopProcess, 0, 0,
nullptr, 0);
1430 incomingMidi.clear();
1435 void reset()
override
1445 void processBlock (AudioBuffer<float>& buffer, MidiBuffer&
midiMessages)
override
1447 jassert (! isUsingDoublePrecision());
1451 void processBlock (AudioBuffer<double>& buffer, MidiBuffer&
midiMessages)
override
1453 jassert (isUsingDoublePrecision());
1457 void processBlockBypassed (AudioBuffer<float>& buffer, MidiBuffer&
midiMessages)
override
1459 jassert (! isUsingDoublePrecision());
1463 void processBlockBypassed (AudioBuffer<double>& buffer, MidiBuffer&
midiMessages)
override
1465 jassert (isUsingDoublePrecision());
1470 bool supportsDoublePrecisionProcessing()
const override
1472 return ((
vstEffect->flags & Vst2::effFlagsCanReplacing) != 0
1473 && (
vstEffect->flags & Vst2::effFlagsCanDoubleReplacing) != 0);
1479 bool canAddBus (
bool)
const override {
return false; }
1480 bool canRemoveBus (
bool)
const override {
return false; }
1482 bool isBusesLayoutSupported (
const BusesLayout&
layouts)
const override
1489 return (
layouts == getBusesLayout());
1496 #if JUCE_IOS || JUCE_ANDROID
1497 bool hasEditor()
const override {
return false; }
1499 bool hasEditor()
const override {
return vstEffect !=
nullptr && (
vstEffect->flags & Vst2::effFlagsHasEditor) != 0; }
1502 AudioProcessorEditor* createEditor()
override;
1510 if (
dispatch (Vst2::effGetInputProperties, index, 0, &
pinProps, 0.0f) != 0)
1523 if (
dispatch (Vst2::effGetInputProperties, index, 0, &
pinProps, 0.0f) != 0)
1524 return (
pinProps.flags & Vst2::kVstPinIsStereo) != 0;
1534 if (
dispatch (Vst2::effGetOutputProperties, index, 0, &
pinProps, 0.0f) != 0)
1547 if (
dispatch (Vst2::effGetOutputProperties, index, 0, &
pinProps, 0.0f) != 0)
1548 return (
pinProps.flags & Vst2::kVstPinIsStereo) != 0;
1556 : getTotalNumOutputChannels());
1563 int getCurrentProgram()
override {
return (
int)
dispatch (Vst2::effGetProgram, 0, 0,
nullptr, 0); }
1565 void setCurrentProgram (
int newIndex)
override
1567 if (getNumPrograms() > 0 &&
newIndex != getCurrentProgram())
1571 const String getProgramName (
int index)
override
1575 if (index == getCurrentProgram())
1580 char nm[264] = { 0 };
1582 if (
dispatch (Vst2::effGetProgramNameIndexed,
jlimit (0, getNumPrograms() - 1, index), -1,
nm, 0) != 0)
1590 void changeProgramName (
int index,
const String& newName)
override
1592 if (index >= 0 && index == getCurrentProgram())
1595 dispatch (Vst2::effSetProgramName, 0, 0, (
void*) newName.substring (0, 24).toRawUTF8(), 0.0f);
1604 void getStateInformation (MemoryBlock&
mb)
override { saveToFXBFile (
mb,
true); }
1605 void getCurrentProgramStateInformation (MemoryBlock&
mb)
override { saveToFXBFile (
mb,
false); }
1607 void setStateInformation (
const void* data,
int size)
override { loadFromFXBFile (data, (
size_t) size); }
1608 void setCurrentProgramStateInformation (
const void* data,
int size)
override { loadFromFXBFile (data, (
size_t) size); }
1611 void timerCallback()
override
1613 if (
dispatch (Vst2::effIdle, 0, 0,
nullptr, 0) == 0)
1617 void handleAsyncUpdate()
override
1619 updateHostDisplay (AudioProcessorListener::ChangeDetails().withProgramChanged (
true)
1620 .withParameterInfoChanged (
true));
1627 case Vst2::audioMasterAutomate:
1628 if (
auto* param = getParameters()[index])
1629 param->sendValueChangedMessageToListeners (opt);
1635 case Vst2::audioMasterProcessEvents:
handleMidiFromPlugin ((
const Vst2::VstEvents*) ptr);
break;
1636 case Vst2::audioMasterGetTime:
return getVSTTime();
1637 case Vst2::audioMasterIdle:
handleIdle();
break;
1638 case Vst2::audioMasterSizeWindow:
setWindowSize (index, (
int) value);
return 1;
1639 case Vst2::audioMasterUpdateDisplay: triggerAsyncUpdate();
break;
1640 case Vst2::audioMasterIOChanged: setLatencySamples (
vstEffect->initialDelay);
break;
1641 case Vst2::audioMasterNeedIdle: startTimer (50);
break;
1651 case Vst2::audioMasterBeginEdit:
1652 if (
auto* param = getParameters()[index])
1653 param->beginChangeGesture();
1659 case Vst2::audioMasterEndEdit:
1660 if (
auto* param = getParameters()[index])
1661 param->endChangeGesture();
1667 case Vst2::audioMasterPinConnected:
return isValidChannel (index, value == 0) ? 0 : 1;
1668 case Vst2::audioMasterGetCurrentProcessLevel:
return isNonRealtime() ? 4 : 0;
1671 case Vst2::audioMasterSetTime:
1672 case Vst2::audioMasterGetParameterQuantization:
1673 case Vst2::audioMasterGetInputLatency:
1674 case Vst2::audioMasterGetOutputLatency:
1675 case Vst2::audioMasterGetPreviousPlug:
1676 case Vst2::audioMasterGetNextPlug:
1677 case Vst2::audioMasterWillReplaceOrAccumulate:
1678 case Vst2::audioMasterOfflineStart:
1679 case Vst2::audioMasterOfflineRead:
1680 case Vst2::audioMasterOfflineWrite:
1681 case Vst2::audioMasterOfflineGetCurrentPass:
1682 case Vst2::audioMasterOfflineGetCurrentMetaPass:
1683 case Vst2::audioMasterGetOutputSpeakerArrangement:
1684 case Vst2::audioMasterVendorSpecific:
1685 case Vst2::audioMasterSetIcon:
1686 case Vst2::audioMasterGetLanguage:
1687 case Vst2::audioMasterOpenWindow:
1688 case Vst2::audioMasterCloseWindow:
1703 case Vst2::audioMasterCanDo:
return handleCanDo ((
const char*) ptr);
1704 case Vst2::audioMasterVersion:
return 2400;
1706 case Vst2::audioMasterGetNumAutomatableParameters:
return 0;
1707 case Vst2::audioMasterGetAutomationState:
return 1;
1708 case Vst2::audioMasterGetVendorVersion:
return 0x0101;
1710 case Vst2::audioMasterGetVendorString:
1711 case Vst2::audioMasterGetProductString:
return getHostName ((
char*) ptr);
1715 case Vst2::audioMasterSetOutputSampleRate:
return 0;
1718 DBG (
"*** Unhandled VST Callback: " + String ((
int)
opcode));
1763 bool loadFromFXBFile (
const void*
const data,
const size_t dataSize)
1768 auto set = (
const fxSet*) data;
1776 if (
fxbSwap (set->numPrograms) >= 0)
1778 auto oldProg = getCurrentProgram();
1782 for (
int i = 0; i <
fxbSwap (set->numPrograms); ++i)
1791 if (
fxbSwap (set->numPrograms) > 0)
1792 setCurrentProgram (i);
1799 if (
fxbSwap (set->numPrograms) > 0)
1819 changeProgramName (getCurrentProgram(),
prog->prgName);
1821 for (
int i = 0; i <
fxbSwap (
prog->numParams); ++i)
1822 if (
auto* param = getParameters()[i])
1845 changeProgramName (getCurrentProgram(),
cset->name);
1855 bool saveToFXBFile (MemoryBlock& dest,
bool isFXB,
int maxSizeMB = 128)
1858 auto numParams = getParameters().size();
1871 set->chunkMagic =
fxbName (
"CcnK");
1873 set->fxMagic =
fxbName (
"FBCh");
1880 chunk.copyTo (set->chunk, 0,
chunk.getSize());
1888 set->chunkMagic =
fxbName (
"CcnK");
1890 set->fxMagic =
fxbName (
"FPCh");
1898 chunk.copyTo (set->chunk, 0,
chunk.getSize());
1907 dest.setSize (len,
true);
1909 auto set = (
fxSet*) dest.getData();
1910 set->chunkMagic =
fxbName (
"CcnK");
1912 set->fxMagic =
fxbName (
"FxBk");
1930 setCurrentProgram (i);
1942 dest.setSize ((
size_t) ((
numParams - 1) * (
int)
sizeof (
float)) +
sizeof (
fxProgram),
true);
1956 void*
data =
nullptr;
1959 if (data !=
nullptr && bytes <= (
size_t)
maxSizeMB * 1024 * 1024)
1962 mb.copyFrom (data, 0, bytes);
1971 bool setChunkData (
const void* data,
const int size,
bool isPreset)
1997 VST2BypassParameter (VSTPluginInstance& effectToUse)
1998 : parent (effectToUse),
2005 void setValue (
float newValue)
override
2009 if (parent.vstSupportsBypass)
2010 parent.dispatch (Vst2::effSetBypass, 0, currentValue ? 1 : 0, nullptr, 0.0f);
2013 float getValueForText (
const String& text)
const override
2015 String lowercaseText (text.toLowerCase());
2017 for (
auto& testText : vstOnStrings)
2018 if (lowercaseText == testText)
2021 for (
auto& testText : vstOffStrings)
2022 if (lowercaseText == testText)
2025 return text.getIntValue() != 0 ? 1.0f : 0.0f;
2028 float getValue()
const override {
return currentValue; }
2029 float getDefaultValue()
const override {
return 0.0f; }
2030 String getName (
int )
const override {
return "Bypass"; }
2031 String getText (
float value,
int)
const override {
return (! approximatelyEqual (value, 0.0f) ?
TRANS (
"On") :
TRANS (
"Off")); }
2032 bool isAutomatable()
const override {
return true; }
2033 bool isDiscrete()
const override {
return true; }
2034 bool isBoolean()
const override {
return true; }
2035 int getNumSteps()
const override {
return 2; }
2036 StringArray getAllValueStrings()
const override {
return values; }
2037 String getLabel()
const override {
return {}; }
2038 String getParameterID()
const override {
return {}; }
2040 VSTPluginInstance& parent;
2041 bool currentValue =
false;
2042 StringArray vstOnStrings, vstOffStrings, values;
2047 CriticalSection
lock;
2052 mutable StringArray programNames;
2057 MidiBuffer incomingMidi;
2072 static const char*
canDos[] = {
"supplyIdle",
2077 "receiveVstMidiEvent",
2083 if (strcmp (
canDos[i], name) == 0)
2094 hostName =
app->getApplicationName();
2096 hostName.copyToUTF8 (name, (
size_t)
jmin (Vst2::kVstMaxVendorStrLen, Vst2::kVstMaxProductStrLen) - 1);
2102 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4311)
2106 JUCE_END_IGNORE_WARNINGS_MSVC
2116 if (getActiveEditor() !=
nullptr)
2117 dispatch (Vst2::effEditIdle, 0, 0,
nullptr, 0);
2121 handleUpdateNowIfNeeded();
2125 p->performAnyPendingRepaintsNow();
2131 #if JUCE_LINUX || JUCE_BSD
2132 const MessageManagerLock mmLock;
2141 Vst2::AEffect*
effect =
nullptr;
2150 if (
module->resFileId != 0)
2178 BusesProperties returnValue;
2194 effect->dispatcher (
effect, Vst2::effSetSpeakerArrangement, 0,
2200 for (
int dir = 0; dir < 2; ++dir)
2202 const bool isInput = (dir == 0);
2203 const int opcode = (isInput ? Vst2::effGetInputProperties : Vst2::effGetOutputProperties);
2205 const auto*
arr = (isInput ? arrangement.in : arrangement.out);
2209 AudioChannelSet layout;
2216 if ((
pinProps.flags & Vst2::kVstPinUseSpeaker) != 0)
2218 layout = SpeakerMappings::vstArrangementTypeToChannelSet (
pinProps.arrangementType, 0);
2220 if (layout.isDisabled())
2223 else if (
arr ==
nullptr)
2231 returnValue.addBus (isInput,
pinProps.label, layout,
true);
2237 String busName = (isInput ?
"Input" :
"Output");
2243 layout = SpeakerMappings::vstArrangementTypeToChannelSet (*
arr);
2247 returnValue.addBus (isInput, busName, layout,
true);
2259 for (
int dir = 0; dir < 2; ++dir)
2261 const bool isInput = (dir == 0);
2262 const int opcode = (isInput ? Vst2::effGetInputProperties : Vst2::effGetOutputProperties);
2274 if ((
pinProps.flags & Vst2::kVstPinUseSpeaker) != 0)
2277 channels = (
pinProps.flags & Vst2::kVstPinIsStereo) != 0 ? 2 : 1;
2286 const Vst2::VstSpeakerArrangement* in;
2287 const Vst2::VstSpeakerArrangement* out;
2289 bool isValid() const noexcept {
return in !=
nullptr && out !=
nullptr; }
2298 if (
effect->numInputs == 0)
2299 return {
nullptr,
nullptr };
2303 Vst2::effGetSpeakerArrangement,
2312 return {
nullptr,
nullptr };
2315 template <
typename Member,
typename Value>
2320 target =
static_cast<Member> (*opt);
2330 template <
typename FloatType>
2347 auto numSamples = buffer.getNumSamples();
2348 auto numChannels = buffer.getNumChannels();
2356 if (
const auto samplePos = position->getTimeInSamples())
2361 if (
auto sig = position->getTimeSignature())
2379 if (position->getIsRecording())
newTransportFlags |= Vst2::kVstTransportRecording;
2382 | Vst2::kVstTransportRecording)))
2389 if (!
fr.hasValue())
2392 switch (
fr->getBaseRate())
2394 case 24:
return fr->isPullDown() ? Vst2::kVstSmpte239fps : Vst2::kVstSmpte24fps;
2395 case 25:
return fr->isPullDown() ? Vst2::kVstSmpte249fps : Vst2::kVstSmpte25fps;
2396 case 30:
return fr->isPullDown() ? (
fr->isDrop() ? Vst2::kVstSmpte2997dfps : Vst2::kVstSmpte2997fps)
2398 case 60:
return fr->isPullDown() ? Vst2::kVstSmpte599fps : Vst2::kVstSmpte60fps;
2406 const auto effectiveRate = position->getFrameRate().hasValue() ? position->getFrameRate()->getEffectiveRate() : 0.0;
2409 if (
const auto loop = position->getLoopPoints())
2420 if (position->getIsLooping())
2421 vstHostTime.flags |= Vst2::kVstTransportCycleActive;
2449 if (numSamples >
tmpBuffer.getNumSamples())
2456 channels[
ch] = (
ch < numChannels ? buffer.getWritePointer (
ch) :
tmpBuffer.getWritePointer (
ch));
2467 for (
int i = getTotalNumOutputChannels(); --i >= 0;)
2468 buffer.clear (i, 0, buffer.getNumSamples());
2476 incomingMidi.clear();
2483 if ((
vstEffect->flags & Vst2::effFlagsCanReplacing) != 0)
2496 for (
int i =
vstEffect->numOutputs; --i >= 0;)
2513 changeProgramName (getCurrentProgram(),
prog->prgName);
2515 for (
int i = 0; i <
fxbSwap (
prog->numParams); ++i)
2516 if (
auto* param = getParameters()[i])
2531 char nm[256] = { 0 };
2543 char nm[256] = { 0 };
2544 dispatch (Vst2::effGetProgramName, 0, 0,
nm, 0);
2548 const int index = getCurrentProgram();
2550 if (index >= 0 && programNames[index].isEmpty())
2552 while (programNames.size() < index)
2553 programNames.add (String());
2555 programNames.set (index,
progName);
2564 auto numParams = getParameters().size();
2577 if (
auto* param = getParameters()[i])
2583 if (
vstEffect !=
nullptr && getNumPrograms() > 0)
2585 char nm[256] = { 0 };
2588 if (
dispatch (Vst2::effGetProgramNameIndexed, 0, -1,
nm, 0) == 0)
2594 for (
int i = 0; i < getNumPrograms(); ++i)
2596 setCurrentProgram (i);
2611 VSTMidiEventList::addEventsToMidiBuffer (
events, incomingMidi);
2627 if (
auto* param = getParameters()[i])
2628 p[i] = param->getValue();
2633 changeProgramName (getCurrentProgram(), (
const char*) m.getData());
2639 if (
auto* param = getParameters()[i])
2640 param->setValue (p[i]);
2655 String getVersion()
const
2657 auto v = (
unsigned int)
dispatch (Vst2::effGetVendorVersion, 0, 0,
nullptr, 0);
2661 if (v == 0 || (
int) v == -1)
2669 unsigned int major = 0, minor = 0,
bugfix = 0, build = 0;
2678 minor = (v % 1000) / 100;
2682 else if (v < 0x10000)
2684 major = (v / 10000);
2685 minor = (v % 10000) / 1000;
2686 bugfix = (v % 1000) / 100;
2687 build = (v % 100) / 10;
2689 else if (v < 0x650000)
2691 major = (v >> 16) & 0xff;
2692 minor = (v >> 8) & 0xff;
2693 bugfix = (v >> 0) & 0xff;
2697 major = (v / 10000000);
2698 minor = (v % 10000000) / 100000;
2699 bugfix = (v % 100000) / 1000;
2703 s << (
int) major <<
'.' << (
int) minor <<
'.' << (
int)
bugfix <<
'.' << (
int) build;
2709 const char* getCategory()
const
2713 case Vst2::kPlugCategEffect:
return "Effect";
2714 case Vst2::kPlugCategSynth:
return "Synth";
2715 case Vst2::kPlugCategAnalysis:
return "Analysis";
2716 case Vst2::kPlugCategMastering:
return "Mastering";
2717 case Vst2::kPlugCategSpacializer:
return "Spacial";
2718 case Vst2::kPlugCategRoomFx:
return "Reverb";
2719 case Vst2::kPlugSurroundFx:
return "Surround";
2720 case Vst2::kPlugCategRestoration:
return "Restoration";
2721 case Vst2::kPlugCategGenerator:
return "Tone generation";
2722 case Vst2::kPlugCategOfflineProcess:
return "Offline Process";
2723 case Vst2::kPlugCategShell:
return "Shell";
2724 case Vst2::kPlugCategUnknown:
return "Unknown";
2725 case Vst2::kPlugCategMaxCount:
2759#if ! (JUCE_IOS || JUCE_ANDROID)
2766 private ComponentMovementWatcher,
2771 VSTPluginWindow (VSTPluginInstance& plug)
2772 : AudioProcessorEditor (&plug),
2774 ComponentMovementWatcher (this),
2778 #if JUCE_LINUX || JUCE_BSD
2779 pluginWindow = None;
2782 ignoreUnused (recursiveResize, pluginRefusesToResize, alreadyInside);
2784 cocoaWrapper.reset (
new NSViewComponentWithParent (plugin));
2785 addAndMakeVisible (cocoaWrapper.get());
2788 activeVSTWindows.add (
this);
2790 Vst2::ERect* rect =
nullptr;
2791 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
2793 if (rect !=
nullptr)
2794 updateSizeFromEditor (rect->right - rect->left, rect->bottom - rect->top);
2796 updateSizeFromEditor (1, 1);
2802 addAndMakeVisible (embeddedComponent);
2806 ~VSTPluginWindow()
override
2808 activeVSTWindows.removeFirstMatchingValue (
this);
2810 closePluginWindow();
2813 cocoaWrapper.reset();
2816 plugin.editorBeingDeleted (
this);
2821 Rectangle<int> vstToComponentRect (Component& editor,
const Rectangle<int>& vr)
const
2823 return editor.getLocalArea (
nullptr, vr / (nativeScaleFactor * getDesktopScaleFactor()));
2826 Rectangle<int> componentToVstRect (Component& editor,
const Rectangle<int>& vr)
const
2828 if (
auto* tl = editor.getTopLevelComponent())
2829 return tl->getLocalArea (&editor, vr) * nativeScaleFactor * tl->getDesktopScaleFactor();
2834 bool updateSizeFromEditor (
int w,
int h)
2836 const auto correctedBounds = vstToComponentRect (*
this, { w, h });
2837 setSize (correctedBounds.getWidth(), correctedBounds.getHeight());
2840 if (cocoaWrapper !=
nullptr)
2841 cocoaWrapper->setSize (correctedBounds.getWidth(), correctedBounds.getHeight());
2848 void paint (Graphics& g)
override
2850 g.fillAll (Colours::black);
2853 void visibilityChanged()
override
2856 openPluginWindow ((NSView*) cocoaWrapper->getView());
2858 closePluginWindow();
2861 void childBoundsChanged (Component*)
override
2863 auto w = cocoaWrapper->getWidth();
2864 auto h = cocoaWrapper->getHeight();
2866 if (w != getWidth() || h != getHeight())
2870 void parentHierarchyChanged()
override { visibilityChanged(); }
2872 float getEffectiveScale()
const
2874 return nativeScaleFactor * userScaleFactor;
2877 void paint (Graphics& g)
override
2879 #if JUCE_LINUX || JUCE_BSD
2882 if (pluginWindow != 0)
2884 auto clip = componentToVstRect (*
this, g.getClipBounds().toNearestInt());
2886 X11Symbols::getInstance()->xClearArea (display, pluginWindow, clip.getX(), clip.getY(),
2887 static_cast<unsigned int> (clip.getWidth()),
2888 static_cast<unsigned int> (clip.getHeight()), True);
2894 g.fillAll (Colours::black);
2898 void componentMovedOrResized (
bool ,
bool )
override
2900 if (recursiveResize)
2903 if (getPeer() !=
nullptr)
2905 const ScopedValueSetter<bool> recursiveResizeSetter (recursiveResize,
true);
2908 embeddedComponent.setBounds (getLocalBounds());
2909 #elif JUCE_LINUX || JUCE_BSD
2910 const auto pos = componentToVstRect (*
this, getLocalBounds());
2912 if (pluginWindow != 0)
2914 auto* symbols = X11Symbols::getInstance();
2915 symbols->xMoveResizeWindow (display,
2919 (
unsigned int) pos.getWidth(),
2920 (
unsigned int) pos.getHeight());
2921 symbols->xMapRaised (display, pluginWindow);
2922 symbols->xFlush (display);
2928 using ComponentMovementWatcher::componentMovedOrResized;
2930 void componentVisibilityChanged()
override
2934 else if (! shouldAvoidDeletingWindow())
2935 closePluginWindow();
2937 setContentScaleFactor();
2939 #if JUCE_LINUX || JUCE_BSD
2940 MessageManager::callAsync ([safeThis = SafePointer<VSTPluginWindow> {
this }]
2942 if (safeThis !=
nullptr)
2943 safeThis->componentMovedOrResized (
true,
true);
2946 componentMovedOrResized (
true,
true);
2950 using ComponentMovementWatcher::componentVisibilityChanged;
2952 void componentPeerChanged()
override
2954 closePluginWindow();
2956 if (getPeer() !=
nullptr)
2959 componentMovedOrResized (
true,
true);
2963 void setContentScaleFactor()
2965 if (pluginRespondsToDPIChanges)
2966 dispatch (Vst2::effVendorSpecific,
2967 (
int) ByteOrder::bigEndianInt (
"PreS"),
2968 (
int) ByteOrder::bigEndianInt (
"AeCs"),
2969 nullptr, getEffectiveScale());
2973 void setScaleFactor (
float scale)
override
2975 userScaleFactor = scale;
2978 setContentScaleFactor();
2987 bool keyStateChanged (
bool)
override {
return pluginWantsKeys; }
2988 bool keyPressed (
const juce::KeyPress&)
override {
return pluginWantsKeys; }
2991 void timerCallback()
override
2996 if (--sizeCheckCount <= 0)
2998 sizeCheckCount = 10;
2999 checkPluginWindowSize();
3003 static bool reentrantGuard =
false;
3005 if (! reentrantGuard)
3007 reentrantGuard =
true;
3012 ScopedThreadDPIAwarenessSetter scope (getPluginHWND());
3014 plugin.dispatch (Vst2::effEditIdle, 0, 0,
nullptr, 0);
3016 reentrantGuard =
false;
3019 #if JUCE_LINUX || JUCE_BSD
3020 if (pluginWindow == 0)
3022 updatePluginWindowHandle();
3024 if (pluginWindow != 0)
3025 componentMovedOrResized (
true,
true);
3032 void mouseDown ([[maybe_unused]]
const MouseEvent& e)
override
3034 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
3039 void broughtToFront()
override
3041 if (activeVSTWindows.removeFirstMatchingValue (
this) != -1)
3042 activeVSTWindows.add (
this);
3045 dispatch (Vst2::effEditTop, 0, 0,
nullptr, 0);
3053 bool shouldAvoidDeletingWindow()
const
3055 return plugin.getPluginDescription()
3056 .manufacturerName.containsIgnoreCase (
"Loud Technologies");
3061 bool shouldRepaintCarbonWindowWhenCreated()
3063 return ! plugin.getName().containsIgnoreCase (
"izotope");
3068 void openPluginWindow (
void* parentWindow)
3070 if (isOpen || parentWindow ==
nullptr)
3075 Vst2::ERect* rect =
nullptr;
3076 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
3077 dispatch (Vst2::effEditOpen, 0, 0, parentWindow, 0);
3080 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
3081 dispatch (Vst2::effGetProgram, 0, 0,
nullptr, 0);
3084 pluginWantsKeys = (dispatch (Vst2::effKeysRequired, 0, 0,
nullptr, 0) == 0);
3087 int w = 250, h = 150;
3089 if (rect !=
nullptr)
3091 w = rect->right - rect->left;
3092 h = rect->bottom - rect->top;
3094 if (w == 0 || h == 0)
3104 updateSizeFromEditor (w, h);
3110 void openPluginWindow()
3115 JUCE_VST_LOG (
"Opening VST UI: " + plugin.getName());
3118 pluginRespondsToDPIChanges = plugin.pluginCanDo (
"supportsViewDpiScaling") > 0;
3120 setContentScaleFactor();
3122 Vst2::ERect* rect =
nullptr;
3124 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
3127 auto* handle = embeddedComponent.getHWND();
3129 auto* handle = getWindowHandle();
3131 dispatch (Vst2::effEditOpen, 0, 0, handle, 0);
3132 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
3133 dispatch (Vst2::effGetProgram, 0, 0,
nullptr, 0);
3135 pluginWantsKeys = (dispatch (Vst2::effKeysRequired, 0, 0,
nullptr, 0) == 0);
3138 originalWndProc =
nullptr;
3139 auto* pluginHWND = getPluginHWND();
3141 if (pluginHWND ==
nullptr)
3148 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4244)
3150 if (! pluginWantsKeys)
3152 originalWndProc = (
void*) GetWindowLongPtr (pluginHWND, GWLP_WNDPROC);
3153 SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) vstHookWndProc);
3156 JUCE_END_IGNORE_WARNINGS_MSVC
3161 ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND };
3162 GetWindowRect (pluginHWND, &r);
3165 auto w = (
int) (r.right - r.left);
3166 auto h = (
int) (r.bottom - r.top);
3168 if (rect !=
nullptr)
3170 auto rw = rect->right - rect->left;
3171 auto rh = rect->bottom - rect->top;
3173 if ((rw > 50 && rh > 50 && rw < 2000 && rh < 2000 && (! isWithin (w, rw, 2) || ! isWithin (h, rh, 2)))
3174 || ((w == 0 && rw > 0) || (h == 0 && rh > 0)))
3177 if (std::abs (rw - w) > 350 || std::abs (rh - h) > 350)
3179 ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND };
3181 SetWindowPos (pluginHWND,
nullptr,
3183 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
3185 GetWindowRect (pluginHWND, &r);
3187 w = r.right - r.left;
3188 h = r.bottom - r.top;
3190 pluginRefusesToResize = (w != rw) || (h != rh);
3197 #elif JUCE_LINUX || JUCE_BSD
3198 updatePluginWindowHandle();
3200 int w = 250, h = 150;
3202 if (rect !=
nullptr)
3204 w = rect->right - rect->left;
3205 h = rect->bottom - rect->top;
3207 if (w == 0 || h == 0)
3214 if (pluginWindow != 0)
3215 X11Symbols::getInstance()->xMapRaised (display, pluginWindow);
3222 updateSizeFromEditor (w, h);
3225 checkPluginWindowSize();
3234 void closePluginWindow()
3242 JUCE_VST_LOG (
"Closing VST UI: " + plugin.getName());
3244 dispatch (Vst2::effEditClose, 0, 0,
nullptr, 0);
3248 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4244)
3249 auto* pluginHWND = getPluginHWND();
3251 if (originalWndProc !=
nullptr && pluginHWND !=
nullptr && IsWindow (pluginHWND))
3252 SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);
3253 JUCE_END_IGNORE_WARNINGS_MSVC
3255 originalWndProc =
nullptr;
3256 #elif JUCE_LINUX || JUCE_BSD
3263 pointer_sized_int dispatch (
const int opcode,
const int index,
const int value,
void*
const ptr,
float opt)
3265 return plugin.dispatch (opcode, index, value, ptr, opt);
3270 bool isWindowSizeCorrectForPlugin (
int w,
int h)
3272 if (pluginRefusesToResize)
3275 const auto converted = vstToComponentRect (*
this, { w, h });
3276 return (isWithin (converted.getWidth(), getWidth(), 5) && isWithin (converted.getHeight(), getHeight(), 5));
3281 Vst2::ERect* rect =
nullptr;
3282 dispatch (Vst2::effEditGetRect, 0, 0, &rect, 0);
3284 auto w = rect->right - rect->left;
3285 auto h = rect->bottom - rect->top;
3287 if (! isWindowSizeCorrectForPlugin (w, h))
3289 updateSizeFromEditor (w, h);
3290 embeddedComponent.updateHWNDBounds();
3295 void checkPluginWindowSize()
3297 if (! pluginRespondsToDPIChanges)
3302 static LRESULT CALLBACK vstHookWndProc (HWND hW, UINT message, WPARAM wParam, LPARAM lParam)
3304 for (
int i = activeVSTWindows.size(); --i >= 0;)
3306 Component::SafePointer<VSTPluginWindow> w (activeVSTWindows[i]);
3308 auto* pluginHWND = w->getPluginHWND();
3310 if (w !=
nullptr && pluginHWND == hW)
3312 if (message == WM_CHAR
3313 || message == WM_KEYDOWN
3314 || message == WM_SYSKEYDOWN
3315 || message == WM_KEYUP
3316 || message == WM_SYSKEYUP
3317 || message == WM_APPCOMMAND)
3319 SendMessage ((HWND) w->getTopLevelComponent()->getWindowHandle(),
3320 message, wParam, lParam);
3324 return CallWindowProc ((WNDPROC) w->originalWndProc,
3326 message, wParam, lParam);
3330 return DefWindowProc (hW, message, wParam, lParam);
3334 #if JUCE_LINUX || JUCE_BSD
3335 void updatePluginWindowHandle()
3337 pluginWindow = getChildWindow ((Window) getWindowHandle());
3345 void resized()
override
3351 VSTPluginInstance& plugin;
3352 float userScaleFactor = 1.0f;
3353 bool isOpen =
false, recursiveResize =
false;
3354 bool pluginWantsKeys =
false, pluginRefusesToResize =
false, alreadyInside =
false;
3357 bool pluginRespondsToDPIChanges =
false;
3359 float nativeScaleFactor = 1.0f;
3361 struct ScaleNotifierCallback
3363 VSTPluginWindow& window;
3365 void operator() (
float platformScale)
const
3367 MessageManager::callAsync ([ref = Component::SafePointer<VSTPluginWindow> (&window), platformScale]
3369 if (
auto* r =
ref.getComponent())
3371 r->nativeScaleFactor = platformScale;
3372 r->setContentScaleFactor();
3376 r->embeddedComponent.updateHWNDBounds();
3378 r->componentMovedOrResized (true, true);
3384 NativeScaleFactorNotifier scaleNotifier {
this, ScaleNotifierCallback { *
this } };
3387 struct ViewComponent final :
public HWNDComponent
3392 inner.addToDesktop (0);
3394 if (
auto* peer = inner.getPeer())
3395 setHWND (peer->getNativeHandle());
3398 void paint (Graphics& g)
override { g.fillAll (Colours::black); }
3401 struct Inner final :
public Component
3403 Inner() { setOpaque (
true); }
3404 void paint (Graphics& g)
override { g.fillAll (Colours::black); }
3410 HWND getPluginHWND()
const
3412 return GetWindow ((HWND) embeddedComponent.getHWND(), GW_CHILD);
3415 ViewComponent embeddedComponent;
3416 void* originalWndProc = {};
3417 int sizeCheckCount = 0;
3418 #elif JUCE_LINUX || JUCE_BSD
3419 ::Display* display = XWindowSystem::getInstance()->getDisplay();
3420 Window pluginWindow = 0;
3423 static constexpr auto nativeScaleFactor = 1.0f;
3431JUCE_END_IGNORE_WARNINGS_MSVC
3434AudioProcessorEditor* VSTPluginInstance::createEditor()
3436 #if JUCE_IOS || JUCE_ANDROID
3446 #if ! JUCE_IOS && ! JUCE_ANDROID
3447 if (
auto* editor =
dynamic_cast<VSTPluginWindow*
> (getActiveEditor()))
3448 return editor->updateSizeFromEditor (w, h);
3460 return instance->handleCallback (
opcode, index, value, ptr, opt);
3462 return VSTPluginInstance::handleGeneralCallback (
opcode, index, value, ptr, opt);
3466VSTPluginFormat::VSTPluginFormat() {}
3467VSTPluginFormat::~VSTPluginFormat() {}
3471 if (
auto p =
format.createInstanceFromDescription (desc, 44100.0, 512))
3476 if (instance->vstModule->resFileId != 0)
3480 instance->fillInPluginDescription (desc);
3491 const String& fileOrIdentifier)
3493 if (! fileMightContainThisPluginType (fileOrIdentifier))
3496 PluginDescription desc;
3497 desc.fileOrIdentifier = fileOrIdentifier;
3498 desc.uniqueId = desc.deprecatedUid = 0;
3502 if (instance ==
nullptr)
3505 if (instance->getVstCategory() != Vst2::kPlugCategShell)
3508 results.add (
new PluginDescription (desc));
3510 instance->dispatch (Vst2::effOpen, 0, 0,
nullptr, 0);
3518 auto uid = (
int) instance->dispatch (Vst2::effShellGetNextPlugin, 0, 0,
shellEffectName, 0);
3523 desc.uniqueId = desc.deprecatedUid = uid;
3526 aboutToScanVSTShellPlugin (desc);
3532 jassert (desc.deprecatedUid == uid);
3533 jassert (desc.uniqueId == uid);
3534 desc.hasSharedContainer =
true;
3538 results.add (
new PluginDescription (desc));
3544void VSTPluginFormat::createPluginInstance (
const PluginDescription& desc,
3545 double sampleRate,
int blockSize,
3546 PluginCreationCallback callback)
3550 if (fileMightContainThisPluginType (desc.fileOrIdentifier))
3552 File file (desc.fileOrIdentifier);
3555 file.getParentDirectory().setAsCurrentWorkingDirectory();
3557 if (
auto module = ModuleHandle::findOrCreateModule (file))
3559 shellUIDToCreate = desc.uniqueId != 0 ? desc.uniqueId : desc.deprecatedUid;
3561 result.
reset (VSTPluginInstance::create (
module, sampleRate, blockSize));
3563 if (result !=
nullptr && ! result->initialiseEffect (sampleRate, blockSize))
3572 if (result ==
nullptr)
3573 errorMsg =
TRANS (
"Unable to load XXX plug-in file").replace (
"XXX",
"VST-2");
3575 callback (std::move (result),
errorMsg);
3578bool VSTPluginFormat::requiresUnblockedMessageThreadDuringCreation (
const PluginDescription&)
const
3587 #if JUCE_MAC || JUCE_IOS
3588 return f.isDirectory() && f.hasFileExtension (
".vst");
3590 return f.existsAsFile() && f.hasFileExtension (
".dll");
3591 #elif JUCE_LINUX || JUCE_BSD || JUCE_ANDROID
3592 return f.existsAsFile() && f.hasFileExtension (
".so");
3598 return fileOrIdentifier;
3603 return File (desc.fileOrIdentifier).getLastModificationTime() != desc.lastFileModTime;
3608 return File (desc.fileOrIdentifier).exists();
3613 StringArray results;
3621void VSTPluginFormat::recursiveFileSearch (StringArray& results,
const File& dir,
const bool recursive)
3625 for (
const auto& iter : RangedDirectoryIterator (dir,
false,
"*", File::findFilesAndDirectories))
3627 auto f = iter.getFile();
3630 if (fileMightContainThisPluginType (f.getFullPathName()))
3633 results.
add (f.getFullPathName());
3637 recursiveFileSearch (results, f,
true);
3644 return FileSearchPath (
"~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST");
3645 #elif JUCE_LINUX || JUCE_BSD || JUCE_ANDROID
3647 "/usr/lib/vst;/usr/local/lib/vst;~/.vst")
3648 .replace (
":",
";"));
3652 FileSearchPath
paths;
3656 paths.removeRedundantPaths();
3672 if (
vst->vstModule !=
nullptr)
3673 return vst->vstModule->vstXml.get();
3681 return vst->loadFromFXBFile (data, dataSize);
3689 return vst->saveToFXBFile (dest,
asFXB);
3713 ModuleHandle::Ptr
module = new ModuleHandle (File(), (MainCall) entryPointFunction);
3719 if (result !=
nullptr)
3721 return result.release();
3739 return dynamic_cast<AudioPluginInstance*
> (
instanceVST);
3747 return vst->dispatch (
opcode, index, value, ptr, opt);
3756JUCE_END_IGNORE_WARNINGS_GCC_LIKE
3757JUCE_END_IGNORE_WARNINGS_MSVC
Holds a resizable array of primitive or copy-by-value objects.
static AudioChannelSet JUCE_CALLTYPE mono()
Creates a one-channel mono set (centre).
static AudioChannelSet JUCE_CALLTYPE stereo()
Creates a set containing a stereo set (left, right).
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
Create a canonical channel set for a given number of channels.
virtual void processBlockBypassed(AudioBuffer< float > &buffer, MidiBuffer &midiMessages)
Renders the next block when the processor is being bypassed.
static int getDefaultNumParameterSteps() noexcept
Returns the default number of steps for a parameter.
static constexpr uint32 bigEndianInt(const void *bytes) noexcept
Turns 4 bytes into a big-endian integer.
static constexpr uint32 littleEndianInt(const void *bytes) noexcept
Turns 4 bytes into a little-endian integer.
static Type swapIfLittleEndian(Type value) noexcept
Swaps the byte order of a signed or unsigned integer if the CPU is little-endian.
static constexpr uint16 swap(uint16 value) noexcept
Swaps the upper and lower bytes of a 16-bit integer.
static int getNumPeers() noexcept
Returns the number of currently-active peers.
static ComponentPeer * getPeer(int index) noexcept
Returns one of the currently-active peers.
const String & getFullPathName() const noexcept
Returns the complete, absolute path of this file.
static File getCurrentWorkingDirectory()
Returns the current working directory.
@ globalApplicationsDirectory
The directory in which applications normally get installed.
@ findFiles
Use this flag to indicate that you want to find files.
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
Finds the location of a special type of file or directory, such as a home folder or documents folder.
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Creates a file that simply contains this string, without doing the sanity-checking that the normal co...
static JUCEApplicationBase * getInstance() noexcept
Returns the global instance of the application object that's running.
Represents a key press, including any modifier keys that are needed.
static MessageManager * getInstance()
Returns the global instance of the MessageManager.
An array designed for holding objects.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
static Random & getSystemRandom() noexcept
The overhead of creating a new Random object is fairly small, but if you want to avoid it,...
A special array for holding a list of strings.
int size() const noexcept
Returns the number of strings in the array.
void add(String stringToAdd)
Appends a string at the end of the array.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
A simple class for holding temporary references to a string literal or String.
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
Returns the start of this string, up to the first occurrence of a substring.
String trim() const
Returns a copy of this string with any whitespace characters removed from the start and end.
bool endsWithChar(juce_wchar character) const noexcept
Tests whether the string ends with a particular character.
float getFloatValue() const noexcept
Parses this string as a floating point number.
bool startsWithChar(juce_wchar character) const noexcept
Tests whether the string begins with a particular character.
String removeCharacters(StringRef charactersToRemove) const
Returns a version of this string with a set of characters removed.
static String createStringFromData(const void *data, int size)
Creates a string from data in an unknown format.
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Creates a String from a UTF-8 encoded buffer.
int getIntValue() const noexcept
Reads the value of the string as a decimal number (up to 32 bits in size).
static String getEnvironmentVariable(const String &name, const String &defaultValue)
Returns an environment variable.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
static void JUCE_CALLTYPE callPendingTimersSynchronously()
For internal use only: invokes any timers that need callbacks.
static String JUCE_CALLTYPE getValue(const String ®ValuePath, const String &defaultValue=String(), WoW64Mode mode=WoW64_Default)
Returns a string from the registry.
Used to build a tree of elements representing an XML document.
int getNumChildElements() const noexcept
Returns the number of sub-elements in this element.
XmlElement * getChildByName(StringRef tagNameToLookFor) const noexcept
Returns the first sub-element with a given tag-name.
double getDoubleAttribute(StringRef attributeName, double defaultReturnValue=0.0) const
Returns the value of a named attribute as floating-point.
bool hasAttribute(StringRef attributeName) const noexcept
Checks whether the element contains an attribute with a certain name.
bool hasTagName(StringRef possibleTagName) const noexcept
Tests whether this element has a particular tag name.
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Returns the value of a named attribute as an integer.
const String & getStringAttribute(StringRef attributeName) const noexcept
Returns the value of a named attribute.
#define TRANS(stringLiteral)
Uses the LocalisedStrings class to translate the given string literal.
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
#define JUCE_ASSERT_MESSAGE_THREAD
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
CriticalSection::ScopedLockType ScopedLock
Automatically locks and unlocks a CriticalSection object.
int pointer_sized_int
A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
signed int int32
A platform-independent 32-bit signed integer type.
int getAddressDifference(Type1 *pointer1, Type2 *pointer2) noexcept
A handy function which returns the difference between any two pointers, in bytes.
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
Attempts to parse some XML text, returning a new XmlElement if it was valid.
void ignoreUnused(Types &&...) noexcept
Handy function for avoiding unused variables warning.
unsigned int pointer_sized_uint
An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it...
Type * addBytesToPointer(Type *basePointer, IntegerType bytes) noexcept
A handy function which adds a number of bytes to any type of pointer and returns the result.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.
long long int64
A platform-independent 64-bit integer type.