26#if JUCE_PLUGINHOST_VST3 && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD)
32#if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS)
33#include <ARA_API/ARAVST3.h>
50using namespace Steinberg;
53#ifndef JUCE_VST3_DEBUGGING
54 #define JUCE_VST3_DEBUGGING 0
57#if JUCE_VST3_DEBUGGING
58 #define VST3_DBG(a) Logger::writeToLog (a);
64static int warnOnFailure (
int result)
noexcept
66 const char*
message =
"Unknown result!";
85static int warnOnFailureIfImplemented (
int result)
noexcept
88 return warnOnFailure (
result);
93 #define warnOnFailure(x) x
94 #define warnOnFailureIfImplemented(x) x
98enum class MediaKind { audio,
event };
100static Vst::MediaType toVstType (MediaKind
x) {
return x == MediaKind::audio ? Vst::kAudio : Vst::kEvent; }
101static Vst::BusDirection toVstType (
Direction x) {
return x == Direction::input ? Vst::kInput : Vst::kOutput; }
103static std::vector<Vst::ParamID> getAllParamIDs (Vst::IEditController&
controller)
105 std::vector<Vst::ParamID>
result;
111 Vst::ParameterInfo
info{};
123class EditControllerParameterDispatcher :
private Timer
126 ~EditControllerParameterDispatcher()
override { stopTimer(); }
133 if (MessageManager::getInstance()->isThisTheMessageThread())
136 cache.set (index,
value);
139 void start (Vst::IEditController& controllerIn)
142 cache = CachedParamValues { getAllParamIDs (controllerIn) };
155 void timerCallback()
override
160 CachedParamValues cache;
165static std::array<uint32, 4> getNormalisedTUID (
const TUID& tuid)
noexcept
167 const FUID fuid { tuid };
168 return { { fuid.getLong1(), fuid.getLong2(), fuid.getLong3(), fuid.getLong4() } };
171template <
typename Range>
172static int getHashForRange (Range&& range)
noexcept
176 for (
const auto& item : range)
182template <
typename ObjectType>
183static void fillDescriptionWith (PluginDescription& description, ObjectType&
object)
186 description.category =
toString (
object.subCategories).
trim();
188 if (description.manufacturerName.trim().isEmpty())
189 description.manufacturerName =
toString (
object.vendor).
trim();
192static void createPluginDescription (PluginDescription& description,
193 const File& pluginFile,
const String& company,
const String&
name,
194 const PClassInfo&
info, PClassInfo2* info2, PClassInfoW* infoW,
195 int numInputs,
int numOutputs)
199 description.lastInfoUpdateTime = Time::getCurrentTime();
200 description.manufacturerName = company;
201 description.name =
name;
202 description.descriptiveName =
name;
203 description.pluginFormatName =
"VST3";
204 description.numInputChannels = numInputs;
205 description.numOutputChannels = numOutputs;
207 description.deprecatedUid = getHashForRange (
info.cid);
208 description.uniqueId = getHashForRange (getNormalisedTUID (
info.cid));
210 if (infoW !=
nullptr) fillDescriptionWith (description, *infoW);
211 else if (info2 !=
nullptr) fillDescriptionWith (description, *info2);
213 if (description.category.isEmpty())
219static int getNumSingleDirectionBusesFor (Vst::IComponent* component,
223 jassert (component !=
nullptr);
225 return (
int) component->getBusCount (toVstType (kind), toVstType (direction));
229static int getNumSingleDirectionChannelsFor (Vst::IComponent* component,
Direction busDirection)
231 jassert (component !=
nullptr);
234 const auto direction = toVstType (busDirection);
235 const Steinberg::int32 numBuses = component->getBusCount (Vst::kAudio, direction);
241 Vst::BusInfo busInfo;
242 warnOnFailure (component->getBusInfo (Vst::kAudio, direction,
i, busInfo));
243 numChannels += ((busInfo.flags & Vst::BusInfo::kDefaultActive) != 0 ? (
int) busInfo.channelCount : 0);
249static void setStateForAllEventBuses (Vst::IComponent* component,
253 jassert (component !=
nullptr);
256 const auto direction = toVstType (busDirection);
257 const Steinberg::int32 numBuses = component->getBusCount (Vst::kEvent, direction);
260 warnOnFailure (component->activateBus (Vst::kEvent, direction,
i, state));
264static void toProcessContext (Vst::ProcessContext& context,
265 AudioPlayHead* playHead,
273 context.sampleRate = sampleRate;
275 const auto position = playHead !=
nullptr ? playHead->getPosition()
280 if (
const auto timeInSamples =
position->getTimeInSamples())
281 context.projectTimeSamples = *timeInSamples;
285 if (
const auto tempo =
position->getBpm())
287 context.state |= ProcessContext::kTempoValid;
288 context.tempo = *tempo;
293 context.state |= ProcessContext::kCycleValid;
294 context.cycleStartMusic =
loop->ppqStart;
295 context.cycleEndMusic =
loop->ppqEnd;
298 if (
const auto sig =
position->getTimeSignature())
300 context.state |= ProcessContext::kTimeSigValid;
301 context.timeSigNumerator = sig->numerator;
302 context.timeSigDenominator = sig->denominator;
305 if (
const auto pos =
position->getPpqPosition())
307 context.state |= ProcessContext::kProjectTimeMusicValid;
308 context.projectTimeMusic = *pos;
311 if (
const auto barStart =
position->getPpqPositionOfLastBarStart())
313 context.state |= ProcessContext::kBarPositionValid;
314 context.barPositionMusic = *barStart;
317 if (
const auto frameRate =
position->getFrameRate())
319 if (
const auto offset =
position->getEditOriginTime())
321 context.state |= ProcessContext::kSmpteValid;
322 context.smpteOffsetSubframes = (
Steinberg::int32) (80.0 * *offset * frameRate->getEffectiveRate());
323 context.frameRate.framesPerSecond = (
Steinberg::uint32) frameRate->getBaseRate();
324 context.frameRate.flags = (
Steinberg::uint32) ((frameRate->isDrop() ? FrameRate::kDropRate : 0)
325 | (frameRate->isPullDown() ? FrameRate::kPullDownRate : 0));
329 if (
const auto hostTime =
position->getHostTimeNs())
331 context.state |= ProcessContext::kSystemTimeValid;
332 context.systemTime = (int64_t) *hostTime;
333 jassert (context.systemTime >= 0);
336 if (
position->getIsPlaying()) context.state |= ProcessContext::kPlaying;
337 if (
position->getIsRecording()) context.state |= ProcessContext::kRecording;
338 if (
position->getIsLooping()) context.state |= ProcessContext::kCycleActive;
343class VST3PluginInstance;
345struct VST3HostContext :
public Vst::IComponentHandler,
346 public Vst::IComponentHandler2,
347 public Vst::IComponentHandler3,
348 public Vst::IContextMenuTarget,
349 public Vst::IHostApplication,
350 public Vst::IUnitHandler,
351 private ComponentRestarter::Listener
358 ~VST3HostContext()
override =
default;
362 FUnknown* getFUnknown() {
return static_cast<Vst::IComponentHandler*
> (
this); }
370 tresult PLUGIN_API beginEdit (Vst::ParamID paramID)
override;
371 tresult PLUGIN_API performEdit (Vst::ParamID paramID, Vst::ParamValue valueNormalized)
override;
372 tresult PLUGIN_API endEdit (Vst::ParamID paramID)
override;
375 tresult PLUGIN_API setDirty (TBool)
override;
378 tresult PLUGIN_API requestOpenEditor (FIDString
name)
override
385 tresult PLUGIN_API startGroupEdit()
override
391 tresult PLUGIN_API finishGroupEdit()
override
397 void setPlugin (VST3PluginInstance* instance)
404 struct ContextMenu :
public Vst::IContextMenu
406 ContextMenu (VST3PluginInstance& pluginInstance) : owner (pluginInstance) {}
407 virtual ~ContextMenu() {}
414 tresult PLUGIN_API addItem (
const Item& item, IContextMenuTarget* target)
override
418 ItemAndTarget newItem;
420 newItem.target = target;
426 tresult PLUGIN_API removeItem (
const Item& toRemove, IContextMenuTarget* target)
override
428 for (
int i = items.size(); --
i >= 0;)
430 auto& item = items.getReference(
i);
432 if (item.item.tag == toRemove.tag && item.target == target)
441 for (
int i = 0;
i < items.size(); ++
i)
443 auto& item = items.getReference(
i);
445 if (item.item.tag == tag)
449 if (target !=
nullptr)
450 *target = item.target;
462 #if ! JUCE_MODAL_LOOPS_PERMITTED
463 static void menuFinished (
int modalResult, VSTComSmartPtr<ContextMenu> menu) { menu->handleResult (modalResult); }
467 enum { zeroTagReplacement = 0x7fffffff };
469 Atomic<int> refCount;
470 VST3PluginInstance& owner;
475 VSTComSmartPtr<IContextMenuTarget> target;
478 Array<ItemAndTarget> items;
480 void handleResult (
int result)
485 if (
result == zeroTagReplacement)
488 for (
int i = 0;
i < items.
size(); ++
i)
492 if ((
int) item.item.tag ==
result)
494 if (item.target !=
nullptr)
505 Vst::IContextMenu* PLUGIN_API createContextMenu (IPlugView*,
const Vst::ParamID*)
override
507 if (plugin !=
nullptr)
508 return new ContextMenu (*plugin);
520 tresult PLUGIN_API getName (Vst::String128
name)
override
522 Steinberg::String str (appName.toUTF8());
523 str.copyTo (
name, 0, 127);
527 tresult PLUGIN_API createInstance (TUID cid, TUID iid,
void** obj)
override
531 if (! doUIDsMatch (cid, iid))
537 if (doUIDsMatch (cid, Vst::IMessage::iid) && doUIDsMatch (iid, Vst::IMessage::iid))
543 if (doUIDsMatch (cid, Vst::IAttributeList::iid) && doUIDsMatch (iid, Vst::IAttributeList::iid))
545 *obj =
new AttributeList;
554 tresult PLUGIN_API notifyUnitSelection (Vst::UnitID)
override
563 tresult PLUGIN_API queryInterface (
const TUID iid,
void** obj)
override
567 UniqueBase<Vst::IComponentHandler>{},
568 UniqueBase<Vst::IComponentHandler2>{},
569 UniqueBase<Vst::IComponentHandler3>{},
570 UniqueBase<Vst::IContextMenuTarget>{},
571 UniqueBase<Vst::IHostApplication>{},
572 UniqueBase<Vst::IUnitHandler>{},
573 SharedBase<FUnknown, Vst::IComponentHandler>{}).extract (obj);
578 VST3PluginInstance* plugin =
nullptr;
579 Atomic<int> refCount;
582 ComponentRestarter componentRestarter { *
this };
584 void restartComponentOnMessageThread (
int32 flags)
override;
591 using Float = double;
592 using String = std::vector<Vst::TChar>;
593 using Binary = std::vector<char>;
595 explicit Attribute (Int
x)
noexcept { constructFrom (std::move (
x)); }
596 explicit Attribute (Float
x)
noexcept { constructFrom (std::move (
x)); }
597 explicit Attribute (String
x)
noexcept { constructFrom (std::move (
x)); }
598 explicit Attribute (Binary
x)
noexcept { constructFrom (std::move (
x)); }
600 Attribute (Attribute&& other)
noexcept
602 moveFrom (std::move (other));
605 Attribute& operator= (Attribute&& other)
noexcept
608 moveFrom (std::move (other));
619 if (kind != Kind::tagInt)
622 result = storage.storedInt;
628 if (kind != Kind::tagFloat)
631 result = storage.storedFloat;
637 if (kind != Kind::tagString)
641 storage.storedString.data(),
642 jmin (
sizeof (Vst::TChar) * storage.storedString.size(), (
size_t) numBytes));
648 if (kind != Kind::tagBinary)
651 data = storage.storedBinary.data();
657 void constructFrom (Int
x)
noexcept { kind = Kind::tagInt;
new (&storage.storedInt) Int (std::move (
x)); }
658 void constructFrom (Float
x)
noexcept { kind = Kind::tagFloat;
new (&storage.storedFloat) Float (std::move (
x)); }
659 void constructFrom (String
x)
noexcept { kind = Kind::tagString;
new (&storage.storedString) String (std::move (
x)); }
660 void constructFrom (Binary
x)
noexcept { kind = Kind::tagBinary;
new (&storage.storedBinary) Binary (std::move (
x)); }
666 case Kind::tagInt:
break;
667 case Kind::tagFloat:
break;
668 case Kind::tagString: storage.storedString.~vector();
break;
669 case Kind::tagBinary: storage.storedBinary.~vector();
break;
673 void moveFrom (Attribute&& other)
noexcept
677 case Kind::tagInt: constructFrom (std::move (other.storage.storedInt));
break;
678 case Kind::tagFloat: constructFrom (std::move (other.storage.storedFloat));
break;
679 case Kind::tagString: constructFrom (std::move (other.storage.storedString));
break;
680 case Kind::tagBinary: constructFrom (std::move (other.storage.storedBinary));
break;
684 enum class Kind { tagInt, tagFloat, tagString, tagBinary };
693 std::vector<Vst::TChar> storedString;
694 std::vector<char> storedBinary;
704 class AttributeList :
public Vst::IAttributeList
707 AttributeList() =
default;
708 virtual ~AttributeList() =
default;
716 return set (attr,
value);
719 tresult PLUGIN_API setFloat (AttrID attr,
double value)
override
721 return set (attr,
value);
724 tresult PLUGIN_API
setString (AttrID attr,
const Vst::TChar*
string)
override
726 return set (attr, std::vector<Vst::TChar> (
string,
string + 1 + tstrlen (
string)));
731 const auto*
ptr =
static_cast<const char*
> (
data);
732 return set (attr, std::vector<char> (ptr, ptr +
size));
737 return get (attr, [&] (
const auto&
x) {
return x.getInt (
result); });
740 tresult PLUGIN_API getFloat (AttrID attr,
double&
result)
override
742 return get (attr, [&] (
const auto&
x) {
return x.getFloat (
result); });
752 return get (attr, [&] (
const auto&
x) {
return x.getBinary (
data,
size); });
756 template <
typename Value>
762 const auto iter = attributes.find (attr);
764 if (iter != attributes.end())
765 iter->second = Attribute (std::move (
value));
767 attributes.emplace (attr, Attribute (std::move (
value)));
772 template <
typename Visitor>
778 const auto iter = attributes.find (attr);
780 if (iter == attributes.cend())
783 return visitor (iter->second);
786 std::map<std::string, Attribute> attributes;
787 Atomic<int> refCount { 1 };
792 struct Message :
public Vst::IMessage
795 virtual ~Message() =
default;
800 FIDString PLUGIN_API getMessageID()
override {
return messageId.toRawUTF8(); }
801 void PLUGIN_API setMessageID (FIDString
id)
override { messageId =
toString (
id); }
802 Vst::IAttributeList* PLUGIN_API getAttributes()
override {
return &attributeList; }
805 AttributeList attributeList;
807 Atomic<int> refCount { 1 };
812 VSTComSmartPtr<AttributeList> attributeList;
818struct DescriptionFactory
820 DescriptionFactory (VST3HostContext* host, IPluginFactory* pluginFactory)
821 : vst3HostContext (host), factory (pluginFactory)
823 jassert (pluginFactory !=
nullptr);
826 virtual ~DescriptionFactory() {}
828 Result findDescriptionsAndPerform (
const File&
file)
830 StringArray foundNames;
831 PFactoryInfo factoryInfo;
832 factory->getFactoryInfo (&factoryInfo);
833 auto companyName =
toString (factoryInfo.vendor).
trim();
837 auto numClasses = factory->countClasses();
841 std::unordered_set<String> araMainFactoryClassNames;
843 #if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS)
847 factory->getClassInfo (
i, &
info);
848 if (std::strcmp (
info.category, kARAMainFactoryClass) == 0)
849 araMainFactoryClassNames.insert (
info.name);
856 factory->getClassInfo (
i, &
info);
861 const String
name (toString (
info.name).trim());
866 std::unique_ptr<PClassInfo2> info2;
867 std::unique_ptr<PClassInfoW> infoW;
870 VSTComSmartPtr<IPluginFactory2> pf2;
871 VSTComSmartPtr<IPluginFactory3> pf3;
873 if (pf2.loadFrom (factory))
875 info2.reset (
new PClassInfo2());
876 pf2->getClassInfo2 (
i, info2.get());
879 if (pf3.loadFrom (factory))
881 infoW.reset (
new PClassInfoW());
882 pf3->getClassInfoUnicode (
i, infoW.get());
888 PluginDescription desc;
891 VSTComSmartPtr<Vst::IComponent> component;
893 if (component.loadFrom (factory,
info.cid))
895 if (component->initialize (vst3HostContext->getFUnknown()) == kResultOk)
897 auto numInputs = getNumSingleDirectionChannelsFor (component, Direction::input);
898 auto numOutputs = getNumSingleDirectionChannelsFor (component, Direction::output);
900 createPluginDescription (desc,
file, companyName,
name,
901 info, info2.get(), infoW.get(), numInputs, numOutputs);
903 component->terminate();
916 if (araMainFactoryClassNames.find (
name) != araMainFactoryClassNames.end())
917 desc.hasARAExtension =
true;
919 if (desc.uniqueId != 0)
920 result = performOnDescription (desc);
929 virtual Result performOnDescription (PluginDescription&) = 0;
932 VSTComSmartPtr<VST3HostContext> vst3HostContext;
933 VSTComSmartPtr<IPluginFactory> factory;
938struct DescriptionLister :
public DescriptionFactory
940 DescriptionLister (VST3HostContext* host, IPluginFactory* pluginFactory)
941 : DescriptionFactory (host, pluginFactory)
945 Result performOnDescription (PluginDescription& desc)
947 list.add (
new PluginDescription (desc));
951 OwnedArray<PluginDescription>
list;
960 DLLHandle (
const File& fileToOpen)
961 : dllFile (fileToOpen)
969 if (bundleRef !=
nullptr)
972 if (factory !=
nullptr)
975 using ExitModuleFn = bool (PLUGIN_API*) ();
977 if (
auto* exitFn = (ExitModuleFn) getFunction (exitFnName))
980 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
992 if (factory ==
nullptr)
1003 void* getFunction (
const char* functionName)
1005 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
1006 return library.getFunction (functionName);
1008 if (bundleRef ==
nullptr)
1011 CFUniquePtr<CFStringRef>
name (String (functionName).toCFString());
1012 return CFBundleGetFunctionPointerForName (bundleRef.get(),
name.get());
1020 IPluginFactory* factory =
nullptr;
1022 static constexpr const char* factoryFnName =
"GetPluginFactory";
1025 static constexpr const char* entryFnName =
"InitDll";
1026 static constexpr const char* exitFnName =
"ExitDll";
1028 using EntryProc = bool (PLUGIN_API*) ();
1029 #elif JUCE_LINUX || JUCE_BSD
1030 static constexpr const char* entryFnName =
"ModuleEntry";
1031 static constexpr const char* exitFnName =
"ModuleExit";
1033 using EntryProc = bool (PLUGIN_API*) (
void*);
1035 static constexpr const char* entryFnName =
"bundleEntry";
1036 static constexpr const char* exitFnName =
"bundleExit";
1038 using EntryProc = bool (*) (CFBundleRef);
1042 #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
1043 DynamicLibrary library;
1049 if (
auto* proc = (EntryProc) getFunction (entryFnName))
1054 if (proc (library.getNativeHandle()))
1070 CFUniquePtr<CFBundleRef> bundleRef;
1076 if (
auto url = CFUniquePtr<CFURLRef> (CFURLCreateFromFileSystemRepresentation (
nullptr,
1077 (
const UInt8*) utf8,
1078 (CFIndex) std::strlen (utf8),
1081 bundleRef.reset (CFBundleCreate (kCFAllocatorDefault, url.get()));
1083 if (bundleRef !=
nullptr)
1085 CFObjectHolder<CFErrorRef>
error;
1087 if (CFBundleLoadExecutableAndReturnError (bundleRef.get(), &
error.object))
1088 if (
auto* proc = (EntryProc) getFunction (entryFnName))
1089 if (proc (bundleRef.get()))
1092 if (
error.object !=
nullptr)
1093 if (
auto failureMessage = CFUniquePtr<CFStringRef> (CFErrorCopyFailureReason (
error.object)))
1094 DBG (String::fromCFString (failureMessage.get()));
1096 bundleRef =
nullptr;
1108struct DLLHandleCache :
public DeletedAtShutdown
1110 DLLHandleCache() =
default;
1111 ~DLLHandleCache()
override { clearSingletonInstance(); }
1115 DLLHandle& findOrCreateHandle (
const String& modulePath)
1117 #if JUCE_LINUX || JUCE_BSD
1118 File
file (getDLLFileFromBundle (modulePath));
1120 File
file (modulePath);
1123 auto it = std::find_if (openHandles.begin(), openHandles.end(),
1124 [&] (
const std::unique_ptr<DLLHandle>& handle)
1126 return file == handle->getFile();
1129 if (it != openHandles.end())
1132 openHandles.push_back (std::make_unique<DLLHandle> (
file));
1133 return *openHandles.back().get();
1137 #if JUCE_LINUX || JUCE_BSD
1138 File getDLLFileFromBundle (
const String& bundlePath)
const
1140 auto machineName = []() -> String
1142 struct utsname unameData;
1143 auto res = uname (&unameData);
1148 return unameData.machine;
1151 File
file (bundlePath);
1153 return file.getChildFile (
"Contents")
1154 .getChildFile (machineName +
"-linux")
1155 .getChildFile (
file.getFileNameWithoutExtension() +
".so");
1159 std::vector<std::unique_ptr<DLLHandle>> openHandles;
1169#if JUCE_LINUX || JUCE_BSD
1171class RunLoop
final :
public Steinberg::Linux::IRunLoop
1174 RunLoop() =
default;
1178 for (
const auto&
h : eventHandlerMap)
1179 LinuxEventLoop::unregisterFdCallback (
h.first);
1183 tresult PLUGIN_API registerEventHandler (Linux::IEventHandler*
handler,
1184 Linux::FileDescriptor fd)
override
1189 auto& handlers = eventHandlerMap[fd];
1191 if (handlers.empty())
1193 LinuxEventLoop::registerFdCallback (fd, [
this] (
int descriptor)
1207 tresult PLUGIN_API unregisterEventHandler (Linux::IEventHandler*
handler)
override
1212 for (
auto iter = eventHandlerMap.begin(), end = eventHandlerMap.end(); iter != end;)
1214 auto& handlers = iter->second;
1216 auto handlersIter = std::find (std::begin (handlers), std::end (handlers),
handler);
1218 if (handlersIter != std::end (handlers))
1220 handlers.erase (handlersIter);
1222 if (handlers.empty())
1224 LinuxEventLoop::unregisterFdCallback (iter->first);
1225 iter = eventHandlerMap.erase (iter);
1237 tresult PLUGIN_API registerTimer (Linux::ITimerHandler*
handler, Linux::TimerInterval milliseconds)
override
1239 if (
handler ==
nullptr || milliseconds <= 0)
1242 timerCallers.emplace_back (
handler, (
int) milliseconds);
1246 tresult PLUGIN_API unregisterTimer (Linux::ITimerHandler*
handler)
override
1248 auto iter = std::find (timerCallers.begin(), timerCallers.end(),
handler);
1250 if (iter == timerCallers.end())
1253 timerCallers.erase (iter);
1258 uint32 PLUGIN_API addRef()
override {
return 1000; }
1259 uint32 PLUGIN_API release()
override {
return 1000; }
1264 struct TimerCaller :
private Timer
1266 TimerCaller (Linux::ITimerHandler*
h,
int interval) :
handler (
h) { startTimer (interval); }
1267 ~TimerCaller()
override { stopTimer(); }
1269 void timerCallback()
override {
handler->onTimer(); }
1271 bool operator== (Linux::ITimerHandler* other)
const noexcept {
return handler == other; }
1273 Linux::ITimerHandler*
handler =
nullptr;
1276 std::unordered_map<Linux::FileDescriptor, std::vector<Linux::IEventHandler*>> eventHandlerMap;
1277 std::list<TimerCaller> timerCallers;
1287struct VST3ModuleHandle :
public ReferenceCountedObject
1289 explicit VST3ModuleHandle (
const File& pluginFile,
const PluginDescription& pluginDesc)
1292 if (open (pluginDesc))
1295 getActiveModules().add (
this);
1302 getActiveModules().removeFirstMatchingValue (
this);
1306 using Ptr = ReferenceCountedObjectPtr<VST3ModuleHandle>;
1308 static VST3ModuleHandle::Ptr findOrCreateModule (
const File&
file,
1309 const PluginDescription& description)
1311 for (
auto* module : getActiveModules())
1314 if (module->file ==
file && module->name == description.name)
1318 VST3ModuleHandle::Ptr modulePtr (
new VST3ModuleHandle (
file, description));
1320 if (! modulePtr->isOpen)
1321 modulePtr =
nullptr;
1329 return DLLHandleCache::getInstance()->findOrCreateHandle (
file.getFullPathName()).getPluginFactory();
1337 static Array<VST3ModuleHandle*>& getActiveModules()
1339 static Array<VST3ModuleHandle*> activeModules;
1340 return activeModules;
1344 bool open (
const PluginDescription& description)
1346 VSTComSmartPtr<IPluginFactory> pluginFactory (DLLHandleCache::getInstance()->findOrCreateHandle (
file.getFullPathName())
1347 .getPluginFactory());
1349 if (pluginFactory !=
nullptr)
1351 auto numClasses = pluginFactory->countClasses();
1356 pluginFactory->getClassInfo (
i, &
info);
1361 if (toString (
info.name).trim() == description.name
1362 && (getHashForRange (getNormalisedTUID (
info.cid)) == description.uniqueId
1363 || getHashForRange (
info.cid) == description.deprecatedUid))
1365 name = description.name;
1376 bool isOpen =
false;
1382template <
typename Type,
size_t N>
1383static int compareWithString (Type (&charArray)[
N],
const String& str)
1390template <
typename Callback>
1391static void forEachARAFactory (IPluginFactory* pluginFactory, Callback&& cb)
1393 #if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS)
1394 const auto numClasses = pluginFactory->countClasses();
1398 pluginFactory->getClassInfo (
i, &
info);
1400 if (std::strcmp (
info.category, kARAMainFactoryClass) == 0)
1402 const bool keepGoing = cb (
info);
1412static std::shared_ptr<const ARA::ARAFactory> getARAFactory (Steinberg::IPluginFactory* pluginFactory,
const String& pluginName)
1414 std::shared_ptr<const ARA::ARAFactory> factory;
1416 #if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS)
1417 forEachARAFactory (pluginFactory,
1418 [&pluginFactory, &pluginName, &factory] (
const auto& pcClassInfo)
1420 if (compareWithString (pcClassInfo.name, pluginName) == 0)
1422 ARA::IMainFactory* source;
1423 if (pluginFactory->
createInstance (pcClassInfo.cid, ARA::IMainFactory::iid, (
void**) &source)
1426 factory = getOrCreateARAFactory (source->getFactory(),
1427 [source] (
const ARA::ARAFactory*) { source->release(); });
1442static std::shared_ptr<const ARA::ARAFactory> getARAFactory (VST3ModuleHandle& module)
1444 auto* pluginFactory =
module.getPluginFactory();
1445 return getARAFactory (pluginFactory, module.getName());
1449struct VST3PluginWindow :
public AudioProcessorEditor,
1450 private ComponentMovementWatcher,
1453 VST3PluginWindow (AudioPluginInstance* owner, IPlugView* pluginView)
1454 : AudioProcessorEditor (owner),
1455 ComponentMovementWatcher (this),
1456 view (pluginView,
false)
1458 , embeddedComponent (*owner)
1465 warnOnFailure (view->setFrame (
this));
1468 setContentScaleFactor();
1472 ~VST3PluginWindow()
override
1474 if (scaleInterface !=
nullptr)
1475 scaleInterface->release();
1477 #if JUCE_LINUX || JUCE_BSD
1478 embeddedComponent.removeClient();
1482 warnOnFailure (view->removed());
1484 warnOnFailure (view->setFrame (
nullptr));
1486 processor.editorBeingDeleted (
this);
1489 embeddedComponent.setView (
nullptr);
1495 #if JUCE_LINUX || JUCE_BSD
1498 if (doUIDsMatch (queryIid, Steinberg::Linux::IRunLoop::iid))
1500 *obj = &runLoop.get();
1515 void paint (Graphics&
g)
override
1517 g.fillAll (Colours::black);
1520 void mouseWheelMove (
const MouseEvent&,
const MouseWheelDetails& wheel)
override
1522 view->onWheel (wheel.deltaY);
1525 void focusGained (FocusChangeType)
override { view->onFocus (
true); }
1526 void focusLost (FocusChangeType)
override { view->onFocus (
false); }
1531 bool keyStateChanged (
bool )
override {
return true; }
1532 bool keyPressed (
const KeyPress& )
override {
return true; }
1536 void componentPeerChanged()
override {}
1539 ViewRect componentToVST3Rect (Rectangle<int>
r)
const
1541 const auto physical = localAreaToGlobal (
r) * nativeScaleFactor * getDesktopScaleFactor();
1542 return { 0, 0, physical.getWidth(), physical.getHeight() };
1546 Rectangle<int> vst3ToComponentRect (
const ViewRect& vr)
const
1548 return getLocalArea (
nullptr, Rectangle<int> { vr.right, vr.bottom } / (nativeScaleFactor * getDesktopScaleFactor()));
1551 void componentMovedOrResized (
bool,
bool wasResized)
override
1553 if (recursiveResize || ! wasResized || getTopLevelComponent()->getPeer() ==
nullptr)
1556 if (view->canResize() == kResultTrue)
1558 auto rect = componentToVST3Rect (getLocalBounds());
1559 view->checkSizeConstraint (&rect);
1562 const ScopedValueSetter<bool> recursiveResizeSetter (recursiveResize,
true);
1564 const auto logicalSize = vst3ToComponentRect (rect);
1568 embeddedComponent.setBounds (getLocalBounds());
1570 view->onSize (&rect);
1575 warnOnFailure (view->getSize (&rect));
1577 resizeWithRect (embeddedComponent, rect);
1581 Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate();
1584 using ComponentMovementWatcher::componentMovedOrResized;
1586 void componentVisibilityChanged()
override
1588 attachPluginWindow();
1590 componentMovedOrResized (
true,
true);
1593 using ComponentMovementWatcher::componentVisibilityChanged;
1598 warnOnFailure (view->getSize (&rect));
1599 resizeWithRect (*
this, rect);
1602 tresult PLUGIN_API resizeView (IPlugView* incomingView, ViewRect* newSize)
override
1604 const ScopedValueSetter<bool> recursiveResizeSetter (recursiveResize,
true);
1606 if (incomingView !=
nullptr && newSize !=
nullptr && incomingView == view)
1608 const auto oldPhysicalSize = componentToVST3Rect (getLocalBounds());
1609 const auto logicalSize = vst3ToComponentRect (*newSize);
1614 embeddedComponent.updateHWNDBounds();
1615 #elif JUCE_LINUX || JUCE_BSD
1616 embeddedComponent.updateEmbeddedBounds();
1621 auto currentPhysicalSize = componentToVST3Rect (getLocalBounds());
1623 if (currentPhysicalSize.getWidth() != oldPhysicalSize.getWidth()
1624 || currentPhysicalSize.getHeight() != oldPhysicalSize.getHeight()
1628 const ScopedValueSetter<bool> inOnSizeSetter (isInOnSize,
true);
1629 view->onSize (¤tPhysicalSize);
1640 void resizeWithRect (Component&
comp,
const ViewRect& rect)
const
1642 const auto logicalSize = vst3ToComponentRect (rect);
1647 void attachPluginWindow()
1649 if (pluginHandle == HandleFormat{})
1652 pluginHandle =
static_cast<HWND> (embeddedComponent.getHWND());
1655 embeddedComponent.setBounds (getLocalBounds());
1656 addAndMakeVisible (embeddedComponent);
1659 pluginHandle = (HandleFormat) embeddedComponent.getView();
1660 #elif JUCE_LINUX || JUCE_BSD
1661 pluginHandle = (HandleFormat) embeddedComponent.getHostWindowID();
1664 if (pluginHandle == HandleFormat{})
1670 const auto attachedResult = view->attached ((
void*) pluginHandle, defaultVST3WindowType);
1673 if (attachedResult == kResultOk)
1674 attachedCalled =
true;
1676 updatePluginScale();
1680 void updatePluginScale()
1682 if (scaleInterface !=
nullptr)
1683 setContentScaleFactor();
1688 void setContentScaleFactor()
1690 if (scaleInterface !=
nullptr)
1701 void setScaleFactor (
float s)
override
1703 userScaleFactor =
s;
1704 setContentScaleFactor();
1708 float getEffectiveScale()
const
1710 return nativeScaleFactor * userScaleFactor;
1714 Atomic<int> refCount { 1 };
1715 VSTComSmartPtr<IPlugView> view;
1718 using HandleFormat =
HWND;
1720 struct ViewComponent :
public HWNDComponent
1725 inner.addToDesktop (0);
1727 if (
auto* peer = inner.getPeer())
1728 setHWND (peer->getNativeHandle());
1731 void paint (Graphics&
g)
override {
g.fillAll (Colours::black); }
1734 struct Inner :
public Component
1736 Inner() { setOpaque (
true); }
1737 void paint (Graphics&
g)
override {
g.fillAll (Colours::black); }
1743 ViewComponent embeddedComponent;
1745 NSViewComponentWithParent embeddedComponent;
1746 using HandleFormat = NSView*;
1747 #elif JUCE_LINUX || JUCE_BSD
1748 SharedResourcePointer<RunLoop> runLoop;
1749 XEmbedComponent embeddedComponent {
true,
false };
1750 using HandleFormat = Window;
1752 Component embeddedComponent;
1753 using HandleFormat =
void*;
1756 HandleFormat pluginHandle = {};
1757 bool recursiveResize =
false, isInOnSize =
false, attachedCalled =
false;
1759 Steinberg::IPlugViewContentScaleSupport* scaleInterface =
nullptr;
1760 float nativeScaleFactor = 1.0f;
1761 float userScaleFactor = 1.0f;
1763 struct ScaleNotifierCallback
1765 VST3PluginWindow&
window;
1767 void operator() (
float platformScale)
const
1769 MessageManager::callAsync ([ref = Component::SafePointer<VST3PluginWindow> (&window), platformScale]
1771 if (
auto*
r = ref.getComponent())
1773 r->nativeScaleFactor = platformScale;
1774 r->setContentScaleFactor();
1778 r->embeddedComponent.updateHWNDBounds();
1779 #elif JUCE_LINUX || JUCE_BSD
1780 r->embeddedComponent.updateEmbeddedBounds();
1787 NativeScaleFactorNotifier scaleNotifier {
this, ScaleNotifierCallback { *
this } };
1796static
bool hasARAExtension (IPluginFactory* pluginFactory,
const String& pluginClassName)
1800 forEachARAFactory (pluginFactory,
1801 [&pluginClassName, &
result] (
const auto& pcClassInfo)
1803 if (compareWithString (pcClassInfo.name, pluginClassName) == 0)
1817struct VST3ComponentHolder
1819 VST3ComponentHolder (
const VST3ModuleHandle::Ptr&
m) : module (
m)
1821 host =
new VST3HostContext();
1824 ~VST3ComponentHolder()
1829 bool isIComponentAlsoIEditController()
const
1831 if (component ==
nullptr)
1837 return VSTComSmartPtr<Vst::IEditController>().loadFrom (component);
1840 bool fetchController (VSTComSmartPtr<Vst::IEditController>& editController)
1842 if (! isComponentInitialised && !
initialise())
1845 editController.loadFrom (component);
1848 TUID controllerCID = { 0 };
1850 if (editController ==
nullptr
1851 && component->getControllerClassId (controllerCID) == kResultTrue
1852 && FUID (controllerCID).isValid())
1854 editController.loadFrom (factory, controllerCID);
1857 if (editController ==
nullptr)
1860 auto numClasses = factory->countClasses();
1864 PClassInfo classInfo;
1865 factory->getClassInfo (
i, &classInfo);
1868 editController.loadFrom (factory, classInfo.cid);
1872 return (editController !=
nullptr);
1876 void fillInPluginDescription (PluginDescription& description)
const
1878 jassert (module !=
nullptr && isComponentInitialised);
1880 PFactoryInfo factoryInfo;
1881 factory->getFactoryInfo (&factoryInfo);
1883 auto classIdx = getClassIndex (module->getName());
1888 bool success = (factory->getClassInfo (classIdx, &
info) == kResultOk);
1892 VSTComSmartPtr<IPluginFactory2> pf2;
1893 VSTComSmartPtr<IPluginFactory3> pf3;
1895 std::unique_ptr<PClassInfo2> info2;
1896 std::unique_ptr<PClassInfoW> infoW;
1898 if (pf2.loadFrom (factory))
1900 info2.reset (
new PClassInfo2());
1901 pf2->getClassInfo2 (classIdx, info2.get());
1908 if (pf3.loadFrom (factory))
1910 pf3->setHostContext (host->getFUnknown());
1911 infoW.reset (
new PClassInfoW());
1912 pf3->getClassInfoUnicode (classIdx, infoW.get());
1920 int totalNumInputChannels = 0, totalNumOutputChannels = 0;
1922 int n = component->getBusCount (Vst::kAudio, Vst::kInput);
1923 for (
int i = 0;
i <
n; ++
i)
1924 if (component->getBusInfo (Vst::kAudio, Vst::kInput,
i, bus) == kResultOk)
1925 totalNumInputChannels += ((bus.flags & Vst::BusInfo::kDefaultActive) != 0 ? bus.channelCount : 0);
1927 n = component->getBusCount (Vst::kAudio, Vst::kOutput);
1928 for (
int i = 0;
i <
n; ++
i)
1929 if (component->getBusInfo (Vst::kAudio, Vst::kOutput,
i, bus) == kResultOk)
1930 totalNumOutputChannels += ((bus.flags & Vst::BusInfo::kDefaultActive) != 0 ? bus.channelCount : 0);
1932 createPluginDescription (description, module->getFile(),
1933 factoryInfo.vendor, module->getName(),
1934 info, info2.get(), infoW.get(),
1935 totalNumInputChannels,
1936 totalNumOutputChannels);
1938 description.hasARAExtension = hasARAExtension (factory, description.name);
1949 if (isComponentInitialised)
1957 factory = VSTComSmartPtr<IPluginFactory> (module->getPluginFactory());
1960 if ((classIdx = getClassIndex (module->getName())) < 0)
1964 if (factory->getClassInfo (classIdx, &
info) != kResultOk)
1967 if (! component.loadFrom (factory,
info.cid) || component ==
nullptr)
1970 cidOfComponent = FUID (
info.cid);
1972 if (warnOnFailure (component->initialize (host->getFUnknown())) != kResultOk)
1975 isComponentInitialised =
true;
1982 if (isComponentInitialised)
1984 component->terminate();
1985 isComponentInitialised =
false;
1988 component =
nullptr;
1992 int getClassIndex (
const String& className)
const
1998 if (factory->getClassInfo (
j, &
info) == kResultOk
2007 VST3ModuleHandle::Ptr module;
2008 VSTComSmartPtr<IPluginFactory> factory;
2009 VSTComSmartPtr<VST3HostContext> host;
2010 VSTComSmartPtr<Vst::IComponent> component;
2011 FUID cidOfComponent;
2013 bool isComponentInitialised =
false;
2022class ParamValueQueue :
public Vst::IParamValueQueue
2026 : paramId (idIn), parameterIndex (parameterIndexIn) {}
2028 virtual ~ParamValueQueue() =
default;
2033 Vst::ParamID PLUGIN_API getParameterId()
override {
return paramId; }
2041 Vst::ParamValue&
value)
override
2043 if (! isPositiveAndBelow (index,
size))
2047 value = cachedValue;
2053 Vst::ParamValue
value,
2057 set ((
float)
value);
2062 void set (
float valueIn)
2064 cachedValue = valueIn;
2077 const Vst::ParamID paramId;
2081 Atomic<int> refCount;
2090class ParameterChanges :
public Vst::IParameterChanges
2096 explicit Entry (std::unique_ptr<ParamValueQueue> queue) :
ptr (queue.release()) {}
2098 VSTComSmartPtr<ParamValueQueue>
ptr;
2102 using Map = std::unordered_map<Vst::ParamID, Entry>;
2103 using Queues = std::vector<Entry*>;
2106 virtual ~ParameterChanges() =
default;
2116 ParamValueQueue* PLUGIN_API getParameterData (
Steinberg::int32 index)
override
2118 if (isPositiveAndBelow (index, queues.size()))
2120 auto& entry = queues[(size_t) index];
2122 jassert (entry->index == index);
2123 return entry->ptr.get();
2129 ParamValueQueue* PLUGIN_API addParameterData (
const Vst::ParamID&
id,
2132 const auto it = map.find (
id);
2134 if (it == map.end())
2137 auto&
result = it->second;
2139 if (
result.index == notInVector)
2142 queues.push_back (&
result);
2149 void set (Vst::ParamID
id,
float value)
2153 if (
auto* queue = addParameterData (
id, indexOut))
2159 for (
auto* item : queues)
2160 item->index = notInVector;
2165 void initialise (
const std::vector<Vst::ParamID>& idsIn)
2169 for (
const auto&
id : idsIn)
2170 map.emplace (
id, Entry { std::make_unique<ParamValueQueue> (
id,
Steinberg::int32 { index++ }) });
2172 queues.reserve (map.size());
2176 template <
typename Callback>
2177 void forEach (Callback&&
callback)
const
2179 for (
const auto* item : queues)
2181 auto*
ptr = item->ptr.get();
2189 Atomic<int> refCount;
2193class VST3PluginInstance
final :
public AudioPluginInstance
2197 struct VST3Parameter
final :
public Parameter
2199 VST3Parameter (VST3PluginInstance&
parent,
2202 bool parameterIsAutomatable)
2203 : pluginInstance (
parent),
2204 vstParamIndex (vstParameterIndex),
2205 paramID (parameterID),
2206 automatable (parameterIsAutomatable)
2210 float getValue()
const override
2212 return pluginInstance.cachedParamValues.get (vstParamIndex);
2217 void setValue (
float newValue)
override
2219 pluginInstance.cachedParamValues.set (vstParamIndex, newValue);
2226 void setValueWithoutUpdatingProcessor (
float newValue)
2228 pluginInstance.cachedParamValues.setWithoutNotifying (vstParamIndex, newValue);
2229 sendValueChangedMessageToListeners (newValue);
2232 String
getText (
float value,
int maximumLength)
const override
2234 MessageManagerLock lock;
2236 if (pluginInstance.editController !=
nullptr)
2240 if (pluginInstance.editController->getParamStringByValue (paramID,
value,
result) == kResultOk)
2244 return Parameter::getText (
value, maximumLength);
2247 float getValueForText (
const String&
text)
const override
2249 MessageManagerLock lock;
2251 if (pluginInstance.editController !=
nullptr)
2255 if (pluginInstance.editController->getParamValueByString (paramID,
toString (
text),
result) == kResultOk)
2259 return Parameter::getValueForText (
text);
2262 float getDefaultValue()
const override
2264 return (
float) getParameterInfo().defaultNormalizedValue;
2267 String getName (
int )
const override
2272 String getLabel()
const override
2277 bool isAutomatable()
const override
2282 bool isDiscrete()
const override
2287 int getNumSteps()
const override
2292 StringArray getAllValueStrings()
const override
2297 String getParameterID()
const override
2299 return String (paramID);
2305 Vst::ParameterInfo getParameterInfo()
const
2307 return pluginInstance.getParameterInfoForIndex (vstParamIndex);
2310 VST3PluginInstance& pluginInstance;
2313 const bool automatable;
2314 const int numSteps = [&]
2316 auto stepCount = getParameterInfo().stepCount;
2317 return stepCount == 0 ? AudioProcessor::getDefaultNumParameterSteps()
2320 const bool discrete = getNumSteps() != AudioProcessor::getDefaultNumParameterSteps();
2324 explicit VST3PluginInstance (std::unique_ptr<VST3ComponentHolder> componentHolder)
2325 : AudioPluginInstance (getBusProperties (componentHolder->component)),
2326 holder (std::
move (componentHolder))
2328 jassert (holder->isComponentInitialised);
2329 holder->host->setPlugin (
this);
2332 ~VST3PluginInstance()
override
2339 jassert (getActiveEditor() ==
nullptr);
2343 if (editControllerConnection !=
nullptr && componentConnection !=
nullptr)
2345 editControllerConnection->disconnect (componentConnection);
2346 componentConnection->disconnect (editControllerConnection);
2349 editController->setComponentHandler (
nullptr);
2351 if (isControllerInitialised && ! holder->isIComponentAlsoIEditController())
2352 editController->terminate();
2354 holder->terminate();
2356 componentConnection =
nullptr;
2357 editControllerConnection =
nullptr;
2360 programListData =
nullptr;
2361 componentHandler2 =
nullptr;
2362 componentHandler =
nullptr;
2363 processor =
nullptr;
2364 midiMapping =
nullptr;
2365 editController2 =
nullptr;
2366 editController =
nullptr;
2377 if (! holder->initialise())
2380 if (! (isControllerInitialised || holder->fetchController (editController)))
2385 if (! holder->isIComponentAlsoIEditController())
2386 editController->initialize (holder->host->getFUnknown());
2388 isControllerInitialised =
true;
2389 editController->setComponentHandler (holder->host);
2390 grabInformationObjects();
2391 interconnectComponentAndController();
2393 auto configureParameters = [
this]
2395 refreshParameterList();
2396 synchroniseStates();
2400 configureParameters();
2405 if (getParameters().isEmpty() && editController->getParameterCount() > 0)
2406 configureParameters();
2408 updateMidiMappings();
2410 parameterDispatcher.start (*editController);
2415 void getExtensions (ExtensionsVisitor& visitor)
const override
2417 struct Extensions :
public ExtensionsVisitor::VST3Client,
2418 public ExtensionsVisitor::ARAClient
2420 explicit Extensions (
const VST3PluginInstance* instanceIn) : instance (instanceIn) {}
2422 Steinberg::Vst::IComponent* getIComponentPtr()
const noexcept override {
return instance->holder->component; }
2424 MemoryBlock getPreset()
const override {
return instance->getStateForPresetFile(); }
2426 bool setPreset (
const MemoryBlock& rawData)
const override
2428 return instance->setStateFromPresetFile (rawData);
2431 void createARAFactoryAsync (std::function<
void (ARAFactoryWrapper)> cb)
const noexcept override
2433 cb (ARAFactoryWrapper { ::juce::getARAFactory (*(instance->holder->module)) });
2436 const VST3PluginInstance* instance =
nullptr;
2439 Extensions extensions {
this };
2440 visitor.visitVST3Client (extensions);
2442 if (::juce::getARAFactory (*(holder->module)))
2444 visitor.visitARAClient (extensions);
2448 void* getPlatformSpecificData()
override {
return holder->component; }
2450 void updateMidiMappings()
2454 const SpinLock::ScopedLockType processLock (processMutex);
2456 if (midiMapping !=
nullptr)
2457 storedMidiMapping.storeMappings (*midiMapping);
2461 const String getName()
const override
2463 auto&
module = holder->module;
2464 return module != nullptr ? module->getName() : String();
2467 void repopulateArrangements (Array<Vst::SpeakerArrangement>& inputArrangements, Array<Vst::SpeakerArrangement>& outputArrangements)
const
2472 auto numInputAudioBuses = getBusCount (
true);
2473 auto numOutputAudioBuses = getBusCount (
false);
2475 for (
int i = 0;
i < numInputAudioBuses; ++
i)
2476 inputArrangements.
add (getArrangementForBus (processor,
true,
i));
2478 for (
int i = 0;
i < numOutputAudioBuses; ++
i)
2479 outputArrangements.
add (getArrangementForBus (processor,
false,
i));
2482 void processorLayoutsToArrangements (Array<Vst::SpeakerArrangement>& inputArrangements, Array<Vst::SpeakerArrangement>& outputArrangements)
2487 auto numInputBuses = getBusCount (
true);
2488 auto numOutputBuses = getBusCount (
false);
2490 for (
int i = 0;
i < numInputBuses; ++
i)
2491 inputArrangements.
add (getVst3SpeakerArrangement (getBus (
true,
i)->getLastEnabledLayout()));
2493 for (
int i = 0;
i < numOutputBuses; ++
i)
2494 outputArrangements.
add (getVst3SpeakerArrangement (getBus (
false,
i)->getLastEnabledLayout()));
2497 void prepareToPlay (
double newSampleRate,
int estimatedSamplesPerBlock)
override
2502 MessageManagerLock lock;
2504 const SpinLock::ScopedLockType processLock (processMutex);
2509 && getBlockSize() == estimatedSamplesPerBlock)
2512 using namespace Vst;
2516 setup.maxSamplesPerBlock = estimatedSamplesPerBlock;
2517 setup.sampleRate = newSampleRate;
2520 warnOnFailure (processor->setupProcessing (setup));
2522 holder->initialise();
2524 Array<Vst::SpeakerArrangement> inputArrangements, outputArrangements;
2525 processorLayoutsToArrangements (inputArrangements, outputArrangements);
2529 auto* inputArrangementData = inputArrangements.
isEmpty() ? &nullArrangement : inputArrangements.
getRawDataPointer();
2530 auto* outputArrangementData = outputArrangements.
isEmpty() ? &nullArrangement : outputArrangements.
getRawDataPointer();
2532 warnOnFailure (processor->setBusArrangements (inputArrangementData, inputArrangements.
size(),
2533 outputArrangementData, outputArrangements.
size()));
2535 Array<Vst::SpeakerArrangement> actualInArr, actualOutArr;
2536 repopulateArrangements (actualInArr, actualOutArr);
2538 jassert (actualInArr == inputArrangements && actualOutArr == outputArrangements);
2541 setRateAndBufferSizeDetails (newSampleRate, estimatedSamplesPerBlock);
2543 auto numInputBuses = getBusCount (
true);
2544 auto numOutputBuses = getBusCount (
false);
2546 for (
int i = 0;
i < numInputBuses; ++
i)
2547 warnOnFailure (holder->component->activateBus (Vst::kAudio, Vst::kInput,
i, getBus (
true,
i)->isEnabled() ? 1 : 0));
2549 for (
int i = 0;
i < numOutputBuses; ++
i)
2550 warnOnFailure (holder->component->activateBus (Vst::kAudio, Vst::kOutput,
i, getBus (
false,
i)->isEnabled() ? 1 : 0));
2552 setLatencySamples (
jmax (0, (
int) processor->getLatencySamples()));
2554 inputBusMap .prepare (createChannelMappings (
true));
2555 outputBusMap.prepare (createChannelMappings (
false));
2557 setStateForAllMidiBuses (
true);
2559 warnOnFailure (holder->component->setActive (
true));
2560 warnOnFailureIfImplemented (processor->setProcessing (
true));
2565 void releaseResources()
override
2567 const SpinLock::ScopedLockType lock (processMutex);
2574 if (processor !=
nullptr)
2575 warnOnFailureIfImplemented (processor->setProcessing (
false));
2577 if (holder->component !=
nullptr)
2578 warnOnFailure (holder->component->setActive (
false));
2580 setStateForAllMidiBuses (
false);
2583 bool supportsDoublePrecisionProcessing()
const override
2585 return (processor->canProcessSampleSize (Vst::kSample64) == kResultTrue);
2597 VST3Parameter* getParameterForID (Vst::ParamID paramID)
const
2599 const auto it = idToParamMap.find (paramID);
2600 return it != idToParamMap.end() ? it->second :
nullptr;
2604 void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
override
2606 jassert (! isUsingDoublePrecision());
2608 const SpinLock::ScopedLockType processLock (processMutex);
2610 if (isActive && processor !=
nullptr)
2611 processAudio (buffer, midiMessages, Vst::kSample32,
false);
2614 void processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)
override
2616 jassert (isUsingDoublePrecision());
2618 const SpinLock::ScopedLockType processLock (processMutex);
2620 if (isActive && processor !=
nullptr)
2621 processAudio (buffer, midiMessages, Vst::kSample64,
false);
2624 void processBlockBypassed (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
override
2626 jassert (! isUsingDoublePrecision());
2628 const SpinLock::ScopedLockType processLock (processMutex);
2630 if (bypassParam !=
nullptr)
2632 if (isActive && processor !=
nullptr)
2633 processAudio (buffer, midiMessages, Vst::kSample32,
true);
2637 AudioProcessor::processBlockBypassed (buffer, midiMessages);
2641 void processBlockBypassed (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)
override
2643 jassert (isUsingDoublePrecision());
2645 const SpinLock::ScopedLockType processLock (processMutex);
2647 if (bypassParam !=
nullptr)
2649 if (isActive && processor !=
nullptr)
2650 processAudio (buffer, midiMessages, Vst::kSample64,
true);
2654 AudioProcessor::processBlockBypassed (buffer, midiMessages);
2659 template <
typename FloatType>
2660 void processAudio (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages,
2661 Vst::SymbolicSampleSizes sampleSize,
bool isProcessBlockBypassedCall)
2663 using namespace Vst;
2664 auto numSamples =
buffer.getNumSamples();
2666 auto numInputAudioBuses = getBusCount (
true);
2667 auto numOutputAudioBuses = getBusCount (
false);
2669 updateBypass (isProcessBlockBypassedCall);
2673 data.symbolicSampleSize = sampleSize;
2674 data.numInputs = numInputAudioBuses;
2675 data.numOutputs = numOutputAudioBuses;
2676 data.inputParameterChanges = inputParameterChanges;
2677 data.outputParameterChanges = outputParameterChanges;
2682 for (
int i = getTotalNumInputChannels();
i <
buffer.getNumChannels(); ++
i)
2683 buffer.clear (
i, 0, numSamples);
2685 inputParameterChanges->clear();
2686 outputParameterChanges->clear();
2688 associateWith (
data, buffer);
2689 associateWith (
data, midiMessages);
2693 inputParameterChanges->set (cachedParamValues.getParamID (index),
value);
2698 parameterDispatcher.push (index,
value);
2701 processor->process (
data);
2705 parameterDispatcher.push (index,
value);
2708 midiMessages.
clear();
2709 MidiEventList::toMidiBuffer (midiMessages, *midiOutputs);
2713 bool canAddBus (
bool)
const override {
return false; }
2714 bool canRemoveBus (
bool)
const override {
return false; }
2716 bool isBusesLayoutSupported (
const BusesLayout& layouts)
const override
2718 const SpinLock::ScopedLockType processLock (processMutex);
2723 return canApplyBusesLayout (layouts);
2727 for (
int dir = 0; dir < 2; ++dir)
2729 bool isInput = (dir == 0);
2730 auto n = getBusCount (isInput);
2732 for (
int i = 0;
i <
n; ++
i)
2733 if (getChannelLayoutOfBus (isInput,
i).isDiscreteLayout())
2740 bool syncBusLayouts (
const BusesLayout& layouts)
const
2742 for (
int dir = 0; dir < 2; ++dir)
2744 bool isInput = (dir == 0);
2745 auto n = getBusCount (isInput);
2746 const Vst::BusDirection vstDir = (isInput ? Vst::kInput : Vst::kOutput);
2748 for (
int busIdx = 0; busIdx <
n; ++busIdx)
2750 const bool isEnabled = (! layouts.getChannelSet (isInput, busIdx).isDisabled());
2752 if (holder->component->activateBus (Vst::kAudio, vstDir, busIdx, (isEnabled ? 1 : 0)) != kResultOk)
2757 Array<Vst::SpeakerArrangement> inputArrangements, outputArrangements;
2759 for (
int i = 0;
i < layouts.inputBuses.size(); ++
i)
2761 const auto& requested = layouts.getChannelSet (
true,
i);
2762 inputArrangements.
add (getVst3SpeakerArrangement (requested.isDisabled() ? getBus (
true,
i)->getLastEnabledLayout() : requested));
2765 for (
int i = 0;
i < layouts.outputBuses.size(); ++
i)
2767 const auto& requested = layouts.getChannelSet (
false,
i);
2768 outputArrangements.
add (getVst3SpeakerArrangement (requested.isDisabled() ? getBus (
false,
i)->getLastEnabledLayout() : requested));
2772 Vst::SpeakerArrangement nullArrangement = {};
2773 auto* inputArrangementData = inputArrangements.
isEmpty() ? &nullArrangement : inputArrangements.
getRawDataPointer();
2774 auto* outputArrangementData = outputArrangements.
isEmpty() ? &nullArrangement : outputArrangements.
getRawDataPointer();
2776 if (processor->setBusArrangements (inputArrangementData, inputArrangements.
size(),
2777 outputArrangementData, outputArrangements.
size()) != kResultTrue)
2781 Array<Vst::SpeakerArrangement> actualIn, actualOut;
2782 repopulateArrangements (actualIn, actualOut);
2784 return (actualIn == inputArrangements && actualOut == outputArrangements);
2787 bool canApplyBusesLayout (
const BusesLayout& layouts)
const override
2793 const auto previousLayout = getBusesLayout();
2794 const auto result = syncBusLayouts (layouts);
2795 syncBusLayouts (previousLayout);
2800 void updateTrackProperties (
const TrackProperties& properties)
override
2802 if (trackInfoListener !=
nullptr)
2804 VSTComSmartPtr<Vst::IAttributeList>
l (
new TrackPropertiesAttributeList (properties));
2805 trackInfoListener->setChannelContextInfos (
l);
2809 struct TrackPropertiesAttributeList :
public Vst::IAttributeList
2811 TrackPropertiesAttributeList (
const TrackProperties& properties) : props (properties) {}
2812 virtual ~TrackPropertiesAttributeList() {}
2816 tresult PLUGIN_API queryInterface (
const TUID queryIid,
void** obj)
override
2820 UniqueBase<Vst::IAttributeList>{},
2821 SharedBase<FUnknown, Vst::IAttributeList>{}).extract (obj);
2833 if (! std::strcmp (
id, Vst::ChannelContext::kChannelNameKey))
2835 Steinberg::String str (props.name.toRawUTF8());
2846 if (! std::strcmp (Vst::ChannelContext::kChannelNameLengthKey,
id))
value = props.name.length();
2847 else if (! std::strcmp (Vst::ChannelContext::kChannelColorKey,
id))
value =
static_cast<Steinberg::int64> (props.colour.getARGB());
2853 Atomic<int> refCount;
2854 TrackProperties props;
2860 String getChannelName (
int channelIndex,
Direction direction)
const
2862 auto numBuses = getNumSingleDirectionBusesFor (holder->component, MediaKind::audio, direction);
2864 int numCountedChannels = 0;
2866 for (
int i = 0;
i < numBuses; ++
i)
2868 auto busInfo = getBusInfo (MediaKind::audio, direction,
i);
2870 numCountedChannels += busInfo.channelCount;
2872 if (channelIndex < numCountedChannels)
2879 const String getInputChannelName (
int channelIndex)
const override {
return getChannelName (channelIndex, Direction::input); }
2880 const String getOutputChannelName (
int channelIndex)
const override {
return getChannelName (channelIndex, Direction::output); }
2882 bool isInputChannelStereoPair (
int channelIndex)
const override
2885 return getOffsetInBusBufferForAbsoluteChannelIndex (
true, channelIndex, busIdx) >= 0
2886 && getBusInfo (MediaKind::audio, Direction::input, busIdx).channelCount == 2;
2889 bool isOutputChannelStereoPair (
int channelIndex)
const override
2892 return getOffsetInBusBufferForAbsoluteChannelIndex (
false, channelIndex, busIdx) >= 0
2893 && getBusInfo (MediaKind::audio, Direction::output, busIdx).channelCount == 2;
2896 bool acceptsMidi()
const override {
return hasMidiInput; }
2897 bool producesMidi()
const override {
return hasMidiOutput; }
2900 AudioProcessorParameter* getBypassParameter()
const override {
return bypassParam; }
2904 double getTailLengthSeconds()
const override
2906 if (processor !=
nullptr)
2910 if (sampleRate > 0.0)
2912 auto tailSamples = processor->getTailSamples();
2914 if (tailSamples == Vst::kInfiniteTail)
2915 return std::numeric_limits<double>::infinity();
2917 return jlimit (0, 0x7fffffff, (
int) processor->getTailSamples()) / sampleRate;
2925 AudioProcessorEditor* createEditor()
override
2927 if (
auto* view = tryCreatingView())
2928 return new VST3PluginWindow (
this, view);
2933 bool hasEditor()
const override
2936 if (getActiveEditor() !=
nullptr)
2939 VSTComSmartPtr<IPlugView> view (tryCreatingView(),
false);
2940 return view !=
nullptr;
2944 int getNumPrograms()
override {
return programNames.size(); }
2945 const String getProgramName (
int index)
override {
return index >= 0 ? programNames[index] : String(); }
2946 void changeProgramName (
int,
const String&)
override {}
2948 int getCurrentProgram()
override
2950 if (programNames.size() > 0 && editController !=
nullptr)
2951 if (
auto* param = getParameterForID (programParameterID))
2952 return jmax (0, roundToInt (param->getValue() * (
float) (programNames.size() - 1)));
2957 void setCurrentProgram (
int program)
override
2959 if (programNames.size() > 0 && editController !=
nullptr)
2961 auto value =
static_cast<Vst::ParamValue
> (program) /
static_cast<Vst::ParamValue
> (
jmax (1, programNames.size() - 1));
2963 if (
auto* param = getParameterForID (programParameterID))
2964 param->setValueNotifyingHost ((
float)
value);
2969 void reset()
override
2971 const SpinLock::ScopedLockType lock (processMutex);
2973 if (holder->component !=
nullptr && processor !=
nullptr)
2975 processor->setProcessing (
false);
2976 holder->component->setActive (
false);
2978 holder->component->setActive (
true);
2979 processor->setProcessing (
true);
2984 void getStateInformation (MemoryBlock& destData)
override
2992 MessageManagerLock lock;
2994 parameterDispatcher.flush();
2996 XmlElement state (
"VST3PluginState");
2998 appendStateFrom (state, holder->component,
"IComponent");
2999 appendStateFrom (state, editController,
"IEditController");
3001 AudioProcessor::copyXmlToBinary (state, destData);
3004 void setStateInformation (
const void*
data,
int sizeInBytes)
override
3012 MessageManagerLock lock;
3014 parameterDispatcher.flush();
3016 if (
auto head = AudioProcessor::getXmlFromBinary (
data, sizeInBytes))
3018 auto componentStream (createMemoryStreamForState (*head,
"IComponent"));
3020 if (componentStream !=
nullptr && holder->component !=
nullptr)
3021 holder->component->setState (componentStream);
3023 if (editController !=
nullptr)
3025 if (componentStream !=
nullptr)
3028 componentStream->seek (0, IBStream::kIBSeekSet, &
result);
3029 setComponentStateAndResetParameters (*componentStream);
3032 auto controllerStream (createMemoryStreamForState (*head,
"IEditController"));
3034 if (controllerStream !=
nullptr)
3035 editController->setState (controllerStream);
3040 void setComponentStateAndResetParameters (Steinberg::MemoryStream& stream)
3042 jassert (editController !=
nullptr);
3044 warnOnFailureIfImplemented (editController->setComponentState (&stream));
3048 void resetParameters()
3050 for (
auto* parameter : getParameters())
3052 auto* vst3Param =
static_cast<VST3Parameter*
> (parameter);
3053 const auto value = (float) editController->getParamNormalized (vst3Param->getParamID());
3054 vst3Param->setValueWithoutUpdatingProcessor (
value);
3058 MemoryBlock getStateForPresetFile()
const
3060 VSTComSmartPtr<Steinberg::MemoryStream> memoryStream (
new Steinberg::MemoryStream(),
false);
3062 if (memoryStream ==
nullptr || holder->component ==
nullptr)
3066 holder->cidOfComponent,
3071 return { memoryStream->getData(),
static_cast<size_t> (memoryStream->getSize()) };
3076 bool setStateFromPresetFile (
const MemoryBlock& rawData)
const
3078 auto rawDataCopy = rawData;
3079 VSTComSmartPtr<Steinberg::MemoryStream> memoryStream (
new Steinberg::MemoryStream (rawDataCopy.getData(), (
int) rawDataCopy.getSize()),
false);
3081 if (memoryStream ==
nullptr || holder->component ==
nullptr)
3085 holder->component, editController,
nullptr);
3089 void fillInPluginDescription (PluginDescription& description)
const override
3091 holder->fillInPluginDescription (description);
3095 void getCurrentProgramStateInformation (MemoryBlock& destData)
override
3101 void setCurrentProgramStateInformation (
const void*
data,
int sizeInBytes)
override
3108 #if JUCE_LINUX || JUCE_BSD
3109 SharedResourcePointer<RunLoop> runLoop;
3112 std::unique_ptr<VST3ComponentHolder> holder;
3114 friend VST3HostContext;
3118 std::unique_ptr<PClassInfo>
info;
3119 std::unique_ptr<PClassInfo2> info2;
3120 std::unique_ptr<PClassInfoW> infoW;
3123 VSTComSmartPtr<Vst::IEditController> editController;
3124 VSTComSmartPtr<Vst::IEditController2> editController2;
3125 VSTComSmartPtr<Vst::IMidiMapping> midiMapping;
3126 VSTComSmartPtr<Vst::IAudioProcessor> processor;
3127 VSTComSmartPtr<Vst::IComponentHandler> componentHandler;
3128 VSTComSmartPtr<Vst::IComponentHandler2> componentHandler2;
3129 VSTComSmartPtr<Vst::IUnitInfo> unitInfo;
3130 VSTComSmartPtr<Vst::IUnitData> unitData;
3131 VSTComSmartPtr<Vst::IProgramListData> programListData;
3132 VSTComSmartPtr<Vst::IConnectionPoint> componentConnection, editControllerConnection;
3133 VSTComSmartPtr<Vst::ChannelContext::IInfoListener> trackInfoListener;
3139 HostBufferMapper inputBusMap, outputBusMap;
3141 StringArray programNames;
3142 Vst::ParamID programParameterID = (Vst::ParamID) -1;
3144 std::map<Vst::ParamID, VST3Parameter*> idToParamMap;
3145 EditControllerParameterDispatcher parameterDispatcher;
3146 StoredMidiMapping storedMidiMapping;
3154 SpinLock processMutex;
3157 template <
typename Type>
3158 static void appendStateFrom (XmlElement& head, VSTComSmartPtr<Type>&
object,
const String& identifier)
3160 if (
object !=
nullptr)
3162 Steinberg::MemoryStream stream;
3164 const auto result =
object->getState (&stream);
3166 if (
result == kResultTrue)
3174 static VSTComSmartPtr<Steinberg::MemoryStream> createMemoryStreamForState (XmlElement& head, StringRef identifier)
3180 if (mem.fromBase64Encoding (state->getAllSubText()))
3182 VSTComSmartPtr<Steinberg::MemoryStream> stream (
new Steinberg::MemoryStream(),
false);
3192 CachedParamValues cachedParamValues;
3193 VSTComSmartPtr<ParameterChanges> inputParameterChanges {
new ParameterChanges };
3194 VSTComSmartPtr<ParameterChanges> outputParameterChanges {
new ParameterChanges };
3195 VSTComSmartPtr<MidiEventList> midiInputs {
new MidiEventList }, midiOutputs {
new MidiEventList };
3196 Vst::ProcessContext timingInfo;
3197 bool isControllerInitialised =
false, isActive =
false, lastProcessBlockCallWasBypass =
false;
3198 const bool hasMidiInput = getNumSingleDirectionBusesFor (holder->component, MediaKind::event, Direction::input) > 0,
3199 hasMidiOutput = getNumSingleDirectionBusesFor (holder->component, MediaKind::event, Direction::output) > 0;
3200 VST3Parameter* bypassParam =
nullptr;
3204 void interconnectComponentAndController()
3206 componentConnection.loadFrom (holder->component);
3207 editControllerConnection.loadFrom (editController);
3209 if (componentConnection !=
nullptr && editControllerConnection !=
nullptr)
3211 warnOnFailure (componentConnection->connect (editControllerConnection));
3212 warnOnFailure (editControllerConnection->connect (componentConnection));
3216 void refreshParameterList()
override
3218 AudioProcessorParameterGroup newParameterTree;
3222 std::map<Vst::UnitID, Vst::UnitInfo> infoMap;
3223 std::map<Vst::UnitID, AudioProcessorParameterGroup*> groupMap;
3224 groupMap[Vst::kRootUnitId] = &newParameterTree;
3226 if (unitInfo !=
nullptr)
3228 const auto numUnits = unitInfo->getUnitCount();
3230 for (
int i = 1;
i < numUnits; ++
i)
3233 unitInfo->getUnitInfo (
i,
ui);
3234 infoMap[
ui.id] = std::move (
ui);
3239 auto allIds = getAllParamIDs (*editController);
3240 inputParameterChanges ->initialise (allIds);
3241 outputParameterChanges->initialise (allIds);
3242 cachedParamValues = CachedParamValues { std::move (allIds) };
3245 for (
int i = 0;
i < editController->getParameterCount(); ++
i)
3247 auto paramInfo = getParameterInfoForIndex (
i);
3248 auto* param =
new VST3Parameter (*
this,
3251 (paramInfo.flags & Vst::ParameterInfo::kCanAutomate) != 0);
3253 if ((paramInfo.flags & Vst::ParameterInfo::kIsBypass) != 0)
3254 bypassParam = param;
3256 std::function<AudioProcessorParameterGroup* (Vst::UnitID)> findOrCreateGroup;
3257 findOrCreateGroup = [&groupMap, &infoMap, &findOrCreateGroup] (Vst::UnitID groupID)
3259 auto existingGroup = groupMap.find (groupID);
3261 if (existingGroup != groupMap.end())
3262 return existingGroup->second;
3264 auto groupInfo = infoMap.find (groupID);
3266 if (groupInfo == infoMap.end())
3267 return groupMap[Vst::kRootUnitId];
3269 auto*
group =
new AudioProcessorParameterGroup (String (groupInfo->first),
3272 groupMap[groupInfo->first] =
group;
3274 auto* parentGroup = findOrCreateGroup (groupInfo->second.parentUnitId);
3275 parentGroup->addChild (std::unique_ptr<AudioProcessorParameterGroup> (group));
3280 auto*
group = findOrCreateGroup (paramInfo.unitId);
3281 group->addChild (std::unique_ptr<AudioProcessorParameter> (param));
3284 setHostedParameterTree (std::move (newParameterTree));
3286 idToParamMap = [
this]
3288 std::map<Vst::ParamID, VST3Parameter*>
result;
3290 for (
auto* parameter : getParameters())
3292 auto* vst3Param =
static_cast<VST3Parameter*
> (parameter);
3293 result.emplace (vst3Param->getParamID(), vst3Param);
3300 void synchroniseStates()
3302 Steinberg::MemoryStream stream;
3304 if (holder->component->getState (&stream) == kResultTrue)
3306 setComponentStateAndResetParameters (stream);
3309 void grabInformationObjects()
3311 processor.loadFrom (holder->component);
3312 unitInfo.loadFrom (holder->component);
3313 programListData.loadFrom (holder->component);
3314 unitData.loadFrom (holder->component);
3315 editController2.loadFrom (holder->component);
3316 midiMapping.loadFrom (holder->component);
3317 componentHandler.loadFrom (holder->component);
3318 componentHandler2.loadFrom (holder->component);
3319 trackInfoListener.loadFrom (holder->component);
3321 if (processor ==
nullptr) processor.loadFrom (editController);
3322 if (unitInfo ==
nullptr) unitInfo.loadFrom (editController);
3323 if (programListData ==
nullptr) programListData.loadFrom (editController);
3324 if (unitData ==
nullptr) unitData.loadFrom (editController);
3325 if (editController2 ==
nullptr) editController2.loadFrom (editController);
3326 if (midiMapping ==
nullptr) midiMapping.loadFrom (editController);
3327 if (componentHandler ==
nullptr) componentHandler.loadFrom (editController);
3328 if (componentHandler2 ==
nullptr) componentHandler2.loadFrom (editController);
3329 if (trackInfoListener ==
nullptr) trackInfoListener.loadFrom (editController);
3332 void setStateForAllMidiBuses (
bool newState)
3334 setStateForAllEventBuses (holder->component, newState, Direction::input);
3335 setStateForAllEventBuses (holder->component, newState, Direction::output);
3338 std::vector<ChannelMapping> createChannelMappings (
bool isInput)
const
3340 std::vector<ChannelMapping>
result;
3341 result.reserve ((
size_t) getBusCount (isInput));
3343 for (
auto i = 0;
i < getBusCount (isInput); ++
i)
3344 result.emplace_back (*getBus (isInput,
i));
3351 setStateForAllMidiBuses (
true);
3353 Vst::ProcessSetup setup;
3354 setup.symbolicSampleSize = Vst::kSample32;
3355 setup.maxSamplesPerBlock = 1024;
3356 setup.sampleRate = 44100.0;
3357 setup.processMode = Vst::kRealtime;
3359 warnOnFailure (processor->setupProcessing (setup));
3361 inputBusMap .prepare (createChannelMappings (
true));
3362 outputBusMap.prepare (createChannelMappings (
false));
3363 setRateAndBufferSizeDetails (setup.sampleRate, (
int) setup.maxSamplesPerBlock);
3366 static AudioProcessor::BusesProperties getBusProperties (VSTComSmartPtr<Vst::IComponent>& component)
3368 AudioProcessor::BusesProperties busProperties;
3369 VSTComSmartPtr<Vst::IAudioProcessor> processor;
3370 processor.loadFrom (component.get());
3372 for (
int dirIdx = 0; dirIdx < 2; ++dirIdx)
3374 const bool isInput = (dirIdx == 0);
3375 const Vst::BusDirection dir = (isInput ? Vst::kInput : Vst::kOutput);
3376 const int numBuses = component->getBusCount (Vst::kAudio, dir);
3378 for (
int i = 0;
i < numBuses; ++
i)
3385 AudioChannelSet layout = (
info.channelCount == 0 ? AudioChannelSet::disabled()
3386 : AudioChannelSet::discreteChannels (
info.channelCount));
3388 Vst::SpeakerArrangement arr;
3389 if (processor !=
nullptr && processor->getBusArrangement (dir,
i, arr) == kResultOk)
3392 busProperties.addBus (isInput, toString (
info.name), layout,
3393 (
info.flags & Vst::BusInfo::kDefaultActive) != 0);
3397 return busProperties;
3401 Vst::BusInfo getBusInfo (MediaKind kind,
Direction direction,
int index = 0)
const
3403 Vst::BusInfo busInfo;
3404 busInfo.mediaType = toVstType (kind);
3405 busInfo.direction = toVstType (direction);
3406 busInfo.channelCount = 0;
3408 holder->component->getBusInfo (busInfo.mediaType, busInfo.direction,
3414 void updateBypass (
bool processBlockBypassedCalled)
3420 if (processBlockBypassedCalled)
3422 if (bypassParam !=
nullptr && (bypassParam->getValue() == 0.0f || ! lastProcessBlockCallWasBypass))
3423 bypassParam->setValue (1.0f);
3427 if (lastProcessBlockCallWasBypass && bypassParam !=
nullptr)
3428 bypassParam->setValue (0.0f);
3432 lastProcessBlockCallWasBypass = processBlockBypassedCalled;
3437 IPlugView* tryCreatingView()
const
3441 IPlugView*
v = editController->createView (Vst::ViewType::kEditor);
3443 if (
v ==
nullptr)
v = editController->createView (
nullptr);
3444 if (
v ==
nullptr) editController->queryInterface (IPlugView::iid, (
void**) &
v);
3450 template <
typename FloatType>
3451 void associateWith (Vst::ProcessData& destination, AudioBuffer<FloatType>& buffer)
3453 destination.inputs = inputBusMap .getVst3LayoutForJuceBuffer (buffer);
3454 destination.outputs = outputBusMap.getVst3LayoutForJuceBuffer (buffer);
3457 void associateWith (Vst::ProcessData& destination, MidiBuffer& midiBuffer)
3459 midiInputs->clear();
3460 midiOutputs->clear();
3464 MidiEventList::hostToPluginEventList (*midiInputs,
3467 [
this] (
const auto controlID,
const auto paramValue)
3469 if (
auto* param = this->getParameterForID (controlID))
3470 param->setValueNotifyingHost ((
float) paramValue);
3474 destination.inputEvents = midiInputs;
3475 destination.outputEvents = midiOutputs;
3478 void updateTimingInformation (Vst::ProcessData& destination,
double processSampleRate)
3480 toProcessContext (timingInfo, getPlayHead(), processSampleRate);
3481 destination.processContext = &timingInfo;
3486 Vst::ParameterInfo paramInfo{};
3488 if (editController !=
nullptr)
3489 editController->getParameterInfo ((
int32) index, paramInfo);
3494 Vst::ProgramListInfo getProgramListInfo (
int index)
const
3496 Vst::ProgramListInfo paramInfo{};
3498 if (unitInfo !=
nullptr)
3499 unitInfo->getProgramListInfo (index, paramInfo);
3504 void syncProgramNames()
3506 programNames.
clear();
3508 if (processor ==
nullptr || editController ==
nullptr)
3511 Vst::UnitID programUnitID;
3512 Vst::ParameterInfo paramInfo{};
3515 int idx, num = editController->getParameterCount();
3517 for (idx = 0; idx < num; ++idx)
3518 if (editController->getParameterInfo (idx, paramInfo) == kResultOk
3525 programParameterID = paramInfo.id;
3526 programUnitID = paramInfo.unitId;
3529 if (unitInfo !=
nullptr)
3531 Vst::UnitInfo uInfo{};
3532 const int unitCount = unitInfo->getUnitCount();
3534 for (
int idx = 0; idx < unitCount; ++idx)
3536 if (unitInfo->getUnitInfo(idx, uInfo) == kResultOk
3537 && uInfo.id == programUnitID)
3539 const int programListCount = unitInfo->getProgramListCount();
3541 for (
int j = 0;
j < programListCount; ++
j)
3543 Vst::ProgramListInfo programListInfo{};
3545 if (unitInfo->getProgramListInfo (
j, programListInfo) == kResultOk
3546 && programListInfo.id == uInfo.programListId)
3548 Vst::String128
name;
3550 for (
int k = 0;
k < programListInfo.programCount; ++
k)
3551 if (unitInfo->getProgramName (programListInfo.id,
k,
name) == kResultOk)
3552 programNames.
add (toString (
name));
3563 if (editController !=
nullptr && paramInfo.stepCount > 0)
3565 auto numPrograms = paramInfo.stepCount + 1;
3567 for (
int i = 0;
i < numPrograms; ++
i)
3569 auto valueNormalized =
static_cast<Vst::ParamValue
> (
i) /
static_cast<Vst::ParamValue
> (paramInfo.stepCount);
3571 Vst::String128 programName;
3572 if (editController->getParamStringByValue (paramInfo.id, valueNormalized, programName) == kResultOk)
3573 programNames.
add (toString (programName));
3584tresult VST3HostContext::beginEdit (Vst::ParamID paramID)
3586 if (plugin ==
nullptr)
3589 if (
auto* param = plugin->getParameterForID (paramID))
3591 param->beginChangeGesture();
3598tresult VST3HostContext::performEdit (Vst::ParamID paramID, Vst::ParamValue valueNormalised)
3600 if (plugin ==
nullptr)
3603 if (
auto* param = plugin->getParameterForID (paramID))
3605 param->setValueNotifyingHost ((
float) valueNormalised);
3608 if (plugin->editController->getParamNormalized (paramID) != (
float) valueNormalised)
3609 return plugin->editController->setParamNormalized (paramID, valueNormalised);
3617tresult VST3HostContext::endEdit (Vst::ParamID paramID)
3619 if (plugin ==
nullptr)
3622 if (
auto* param = plugin->getParameterForID (paramID))
3624 param->endChangeGesture();
3638 componentRestarter.restart (flags);
3642tresult PLUGIN_API VST3HostContext::setDirty (TBool needsSave)
3645 plugin->updateHostDisplay (AudioPluginInstance::ChangeDetails{}.withNonParameterStateChanged (
true));
3650void VST3HostContext::restartComponentOnMessageThread (
int32 flags)
3652 if (plugin ==
nullptr)
3658 if (hasFlag (flags, Vst::kReloadComponent))
3661 if (hasFlag (flags, Vst::kIoChanged))
3663 auto sampleRate = plugin->getSampleRate();
3664 auto blockSize = plugin->getBlockSize();
3667 plugin->releaseResources();
3668 plugin->prepareToPlay (sampleRate >= 8000 ? sampleRate : 44100.0,
3669 blockSize > 0 ? blockSize : 1024);
3672 if (hasFlag (flags, Vst::kLatencyChanged))
3673 if (plugin->processor !=
nullptr)
3674 plugin->setLatencySamples (
jmax (0, (
int) plugin->processor->getLatencySamples()));
3676 if (hasFlag (flags, Vst::kMidiCCAssignmentChanged))
3677 plugin->updateMidiMappings();
3679 if (hasFlag (flags, Vst::kParamValuesChanged))
3680 plugin->resetParameters();
3682 plugin->updateHostDisplay (AudioProcessorListener::ChangeDetails().withProgramChanged (
true)
3683 .withParameterInfoChanged (
true));
3689 Array<const Item*> subItemStack;
3690 OwnedArray<PopupMenu> menuStack;
3691 PopupMenu* topLevelMenu = menuStack.add (
new PopupMenu());
3693 for (
int i = 0;
i < items.
size(); ++
i)
3696 auto* menuToUse = menuStack.getLast();
3698 if (hasFlag (item.flags, Item::kIsGroupStart & ~Item::kIsDisabled))
3700 subItemStack.
add (&item);
3701 menuStack.add (
new PopupMenu());
3703 else if (hasFlag (item.flags, Item::kIsGroupEnd))
3705 if (
auto* subItem = subItemStack.
getLast())
3707 if (
auto*
m = menuStack [menuStack.size() - 2])
3708 m->addSubMenu (toString (subItem->name), *menuToUse,
3709 ! hasFlag (subItem->flags, Item::kIsDisabled),
3711 hasFlag (subItem->flags, Item::kIsChecked));
3713 menuStack.removeLast (1);
3717 else if (hasFlag (item.flags, Item::kIsSeparator))
3719 menuToUse->addSeparator();
3723 menuToUse->addItem (item.tag != 0 ? (
int) item.tag : (
int) zeroTagReplacement,
3725 ! hasFlag (item.flags, Item::kIsDisabled),
3726 hasFlag (item.flags, Item::kIsChecked));
3730 PopupMenu::Options options;
3732 if (
auto* ed = owner.getActiveEditor())
3734 #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
3735 if (
auto* peer = ed->getPeer())
3737 auto scale = peer->getPlatformScaleFactor();
3744 options = options.withTargetScreenArea (ed->getScreenBounds().translated ((
int)
x, (
int)
y).withSize (1, 1));
3747 #if JUCE_MODAL_LOOPS_PERMITTED
3749 handleResult (topLevelMenu->showMenu (options));
3751 topLevelMenu->showMenuAsync (options, ModalCallbackFunction::create (menuFinished, VSTComSmartPtr<ContextMenu> (
this)));
3760 if (plugin !=
nullptr)
3761 plugin->syncProgramNames();
3768VST3PluginFormat::VST3PluginFormat() =
default;
3769VST3PluginFormat::~VST3PluginFormat() =
default;
3771bool VST3PluginFormat::setStateFromVSTPresetFile (AudioPluginInstance* api,
const MemoryBlock& rawData)
3773 if (
auto vst3 =
dynamic_cast<VST3PluginInstance*
> (api))
3774 return vst3->setStateFromPresetFile (rawData);
3779void VST3PluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& results,
const String& fileOrIdentifier)
3781 if (fileMightContainThisPluginType (fileOrIdentifier))
3789 VSTComSmartPtr<IPluginFactory> pluginFactory (DLLHandleCache::getInstance()->findOrCreateHandle (fileOrIdentifier)
3792 if (pluginFactory !=
nullptr)
3794 VSTComSmartPtr<VST3HostContext> host (
new VST3HostContext());
3795 DescriptionLister lister (host, pluginFactory);
3796 lister.findDescriptionsAndPerform (File (fileOrIdentifier));
3798 results.addCopiesOf (lister.list);
3807void VST3PluginFormat::createARAFactoryAsync (
const PluginDescription& description, ARAFactoryCreationCallback
callback)
3809 if (! description.hasARAExtension)
3812 callback ({ {},
"The provided plugin does not support ARA features" });
3815 File
file (description.fileOrIdentifier);
3816 VSTComSmartPtr<IPluginFactory> pluginFactory (
3817 DLLHandleCache::getInstance()->findOrCreateHandle (
file.getFullPathName()).getPluginFactory());
3818 const auto* pluginName = description.name.
toRawUTF8();
3820 callback ({ ARAFactoryWrapper { ::juce::getARAFactory (pluginFactory, pluginName) }, {} });
3823static std::unique_ptr<AudioPluginInstance> createVST3Instance (VST3PluginFormat&
format,
3824 const PluginDescription& description)
3826 if (!
format.fileMightContainThisPluginType (description.fileOrIdentifier))
3829 const File
file { description.fileOrIdentifier };
3831 struct ScopedWorkingDirectory
3833 ~ScopedWorkingDirectory() { previousWorkingDirectory.setAsCurrentWorkingDirectory(); }
3837 const ScopedWorkingDirectory
scope;
3838 file.getParentDirectory().setAsCurrentWorkingDirectory();
3840 const VST3ModuleHandle::Ptr module { VST3ModuleHandle::findOrCreateModule (
file, description) };
3842 if (module ==
nullptr)
3845 auto holder = std::make_unique<VST3ComponentHolder> (module);
3847 if (! holder->initialise())
3850 auto instance = std::make_unique<VST3PluginInstance> (std::move (holder));
3852 if (! instance->initialise())
3858void VST3PluginFormat::createPluginInstance (
const PluginDescription& description,
3859 double,
int, PluginCreationCallback
callback)
3861 auto result = createVST3Instance (*
this, description);
3863 const auto errorMsg =
result ==
nullptr ?
TRANS (
"Unable to load XXX plug-in file").replace (
"XXX",
"VST-3")
3869bool VST3PluginFormat::requiresUnblockedMessageThreadDuringCreation (
const PluginDescription&)
const
3874bool VST3PluginFormat::fileMightContainThisPluginType (
const String& fileOrIdentifier)
3878 return f.hasFileExtension (
".vst3")
3879 #if JUCE_MAC || JUCE_LINUX || JUCE_BSD
3882 &&
f.existsAsFile();
3886String VST3PluginFormat::getNameOfPluginFromIdentifier (
const String& fileOrIdentifier)
3888 return fileOrIdentifier;
3891bool VST3PluginFormat::pluginNeedsRescanning (
const PluginDescription& description)
3893 return File (description.fileOrIdentifier).getLastModificationTime() != description.lastFileModTime;
3896bool VST3PluginFormat::doesPluginStillExist (
const PluginDescription& description)
3898 return File (description.fileOrIdentifier).exists();
3901StringArray VST3PluginFormat::searchPathsForPlugins (
const FileSearchPath& directoriesToSearch,
const bool recursive,
bool)
3903 StringArray results;
3905 for (
int i = 0;
i < directoriesToSearch.getNumPaths(); ++
i)
3906 recursiveFileSearch (results, directoriesToSearch[
i], recursive);
3911void VST3PluginFormat::recursiveFileSearch (StringArray& results,
const File& directory,
const bool recursive)
3915 auto f = iter.getFile();
3918 if (fileMightContainThisPluginType (
f.getFullPathName()))
3921 results.
add (
f.getFullPathName());
3924 if (recursive && (! isPlugin) &&
f.isDirectory())
3925 recursiveFileSearch (results,
f,
true);
3929FileSearchPath VST3PluginFormat::getDefaultLocationsToSearch()
3934 return FileSearchPath (localAppData +
"\\Programs\\Common\\VST3;" + programFiles +
"\\Common Files\\VST3");
3936 return FileSearchPath (
"~/Library/Audio/Plug-Ins/VST3;/Library/Audio/Plug-Ins/VST3");
3938 return FileSearchPath (
"~/.vst3/;/usr/lib/vst3/;/usr/local/lib/vst3/");
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
Direction
Definition CarlaStyle.cpp:109
class MasterUI * ui
Definition Connection.cpp:39
Controller controller
Definition main.C:5
#define noexcept
Definition DistrhoDefines.h:72
#define final
Definition DistrhoDefines.h:74
static Audio_Scope * scope
Definition player.cpp:26
goto loop
Definition Spc_Cpu.h:155
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
event_queue * push(event_queue *queue, event_queue *event)
Definition allegrosmfwr.cpp:114
int64_t int64
Definition basics.h:91
int32_t int32
Definition basics.h:89
uint32_t uint32
Definition basics.h:90
static const LV2_Descriptor descriptor
Definition bindings_test_plugin.c:165
ElementType & getReference(const int index) const noexcept
Definition Array.h:243
void clearQuick() noexcept
Definition Array.h:179
void removeLast(int howManyToRemove=1)
Definition Array.h:907
bool add(const ElementType &newElement) noexcept
Definition Array.h:354
int size() const noexcept
Definition Array.h:187
ElementType getLast() const
Definition Array.h:268
ElementType * getRawDataPointer() noexcept
Definition Array.h:283
bool isEmpty() const noexcept
Definition Array.h:193
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Definition File.cpp:65
static File getCurrentWorkingDirectory()
Definition File.cpp:1395
int64 getLastModificationTime() const
Definition File.cpp:534
@ findFilesAndDirectories
Definition File.h:463
bool isDirectory() const
Definition File.cpp:1306
const String & getFullPathName() const noexcept
Definition File.h:152
static File getSpecialLocation(const SpecialLocationType type)
Definition File.cpp:1642
size_t getSize() const noexcept
Definition MemoryBlock.h:102
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Definition MemoryBlock.cpp:109
void copyTo(void *destData, int sourceOffset, size_t numBytes) const noexcept
Definition MemoryBlock.cpp:240
void clear() noexcept
Definition MidiBuffer.cpp:106
static Result ok() noexcept
Definition Result.h:68
@ kIBSeekSet
set absolute seek position
Definition ibstream.h:34
float ScaleFactor
Definition iplugviewcontentscalesupport.h:53
static const FUID iid
Definition iplugviewcontentscalesupport.h:57
virtual tresult PLUGIN_API createInstance(FIDString cid, FIDString _iid, void **obj)=0
char * getData() const
returns the memory pointer
Definition memorystream.cpp:261
tresult PLUGIN_API seek(int64 pos, int32 mode, int64 *result) SMTG_OVERRIDE
Definition memorystream.cpp:154
void setSize(TSize size)
set the memory size, a realloc will occur if memory already used
Definition memorystream.cpp:196
TSize getSize() const
returns the current memory size
Definition memorystream.cpp:190
static bool loadPreset(IBStream *stream, const FUID &classID, IComponent *component, IEditController *editController=nullptr, std::vector< FUID > *otherClassIDArray=nullptr)
Definition vstpresetfile.cpp:144
static bool savePreset(IBStream *stream, const FUID &classID, IComponent *component, IEditController *editController=nullptr, const char *xmlBuffer=nullptr, int32 xmlSize=-1)
Definition vstpresetfile.cpp:102
void clear()
Definition StringArray.cpp:84
bool add(const String &stringToAdd)
Definition StringArray.cpp:108
bool contains(StringRef stringToLookFor, bool ignoreCase=false) const
Definition StringArray.cpp:152
size_t getNumBytesAsUTF8() const noexcept
Definition String.cpp:1956
const char * toRawUTF8() const
Definition String.cpp:1925
XmlElement * getChildByName(StringRef tagNameToLookFor) const noexcept
Definition XmlElement.cpp:613
XmlElement * createNewChildElement(StringRef tagName)
Definition XmlElement.cpp:668
const String & getFullPathName() const noexcept
Definition juce_File.h:153
String trim() const
Definition juce_String.cpp:1656
bool containsIgnoreCase(StringRef text) const noexcept
Definition juce_String.cpp:1045
String substring(int startIndex, int endIndex) const
Definition juce_String.cpp:1498
String getFileNameWithoutExtension() const
Definition File.cpp:378
const char * toRawUTF8() const
Definition String.cpp:1925
void addTextElement(const String &text)
Definition XmlElement.cpp:904
int * l
Definition inflate.c:1579
unsigned * m
Definition inflate.c:1559
register unsigned k
Definition inflate.c:946
register unsigned j
Definition inflate.c:1576
int y
Definition inflate.c:1588
unsigned v[N_MAX]
Definition inflate.c:1584
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
unsigned f
Definition inflate.c:1572
#define DEF_CLASS_IID(ClassName)
Definition funknown.h:78
static PuglViewHint int value
Definition pugl.h:1708
static const char * title
Definition pugl.h:1747
static const char * name
Definition pugl.h:1582
static uintptr_t parent
Definition pugl.h:1644
virtual ASIOError start()=0
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate)=0
Steinberg::IPluginFactory *(PLUGIN_API * GetFactoryProc)()
Definition ipluginbase.h:424
#define kVstAudioEffectClass
Definition ivstaudioprocessor.h:30
#define kVstComponentControllerClass
Definition ivsteditcontroller.h:30
struct backing_store_struct * info
Definition jmemsys.h:183
JSAMPIMAGE data
Definition jpeglib.h:945
int version
Definition jpeglib.h:901
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_NO_SANITIZE
Definition juce_CompilerWarnings.h:218
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
#define JUCE_BEGIN_NO_SANITIZE(warnings)
Definition juce_CompilerWarnings.h:217
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
Definition juce_MessageManager.h:465
#define JUCE_ASSERT_MESSAGE_THREAD
Definition juce_MessageManager.h:473
#define JUCE_IMPLEMENT_SINGLETON(Classname)
Definition juce_Singleton.h:201
#define JUCE_DECLARE_SINGLETON(Classname, doNotRecreateAfterDeletion)
Definition juce_Singleton.h:184
#define JUCE_DECLARE_VST3_COM_REF_METHODS
Definition juce_VST3Common.h:36
#define JUCE_DECLARE_VST3_COM_QUERY_METHODS
Definition juce_VST3Common.h:40
static void cleanup(void)
Definition lilv_test.c:152
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition juce_ARACommon.h:29
uint32 ParamID
parameter identifier
Definition vsttypes.h:75
@ kRealtime
realtime processing
Definition ivstaudioprocessor.h:140
@ kOffline
offline processing
Definition ivstaudioprocessor.h:142
uint64 SpeakerArrangement
Bitset of speakers.
Definition vsttypes.h:98
@ kSample32
32-bit precision
Definition ivstaudioprocessor.h:112
@ kSample64
64-bit precision
Definition ivstaudioprocessor.h:113
int int32
Definition ftypes.h:50
int8 TUID[16]
plain UID type
Definition funknown.h:210
const char8 * FIDString
Definition ftypes.h:117
@ kNoInterface
Definition funknown.h:192
@ kResultOk
Definition funknown.h:193
@ kInvalidArgument
Definition funknown.h:196
@ kInternalError
Definition funknown.h:198
@ kOutOfMemory
Definition funknown.h:200
@ kNotImplemented
Definition funknown.h:197
@ kResultFalse
Definition funknown.h:195
@ kResultTrue
Definition funknown.h:194
@ kNotInitialized
Definition funknown.h:199
long long int64
Definition ftypes.h:66
int32 UCoord
Definition ftypes.h:135
int32 tresult
Definition ftypes.h:76
unsigned int uint32
Definition ftypes.h:51
void initialise()
Definition hardgate.cpp:79
void setInt(int value, VARIANT *variant)
Definition juce_win32_UIAHelpers.h:47
void setString(const String &value, VARIANT *variant)
Definition juce_win32_UIAHelpers.h:59
void clear(void *s)
Definition juce_FixedSizeFunction.h:71
void move(void *from, void *to)
Definition juce_FixedSizeFunction.h:53
auto & get(ProcessorChain< Processors... > &chain) noexcept
Definition juce_ProcessorChain.h:133
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition carla_juce.cpp:31
InterfaceResultWithDeferredAddRef testForMultiple(ToTest &, const Steinberg::TUID)
Definition juce_VST3Common.h:140
void zerostruct(Type &structure) noexcept
Definition juce_Memory.h:32
void callOnMessageThread(Callback &&callback)
Definition juce_audio_processors.cpp:81
juce::String toString(const Steinberg::char8 *string) noexcept
Definition juce_VST3Common.h:159
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
AudioChannelSet getChannelSetForSpeakerArrangement(Steinberg::Vst::SpeakerArrangement arr) noexcept
Definition juce_VST3Common.h:478
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags const jack_port_t port jack_client_t jack_port_id_t port_id const jack_port_t const char port_name const jack_port_t port void * ptr
Definition juce_linux_JackAudio.cpp:79
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
int roundToInt(const FloatType value) noexcept
Definition juce_MathsFunctions.h:465
@ window
Definition juce_AccessibilityRole.h:63
@ list
Definition juce_AccessibilityRole.h:56
@ group
Definition juce_AccessibilityRole.h:61
constexpr int numElementsInArray(Type(&)[N]) noexcept
Definition juce_MathsFunctions.h:344
constexpr Nullopt nullopt
Definition juce_Optional.h:48
QString getString(MimeType mT)
Definition Clipboard.cpp:62
auto getText(std::string_view name) -> QString
Definition embed.cpp:125
auto logicalSize(const QPixmap &pixmap) noexcept
Temporary shim for QPixmap::deviceIndependentSize.
Definition embed.h:61
PluginFactory * getPluginFactory()
Definition PluginFactory.cpp:103
QPoint position(const QDropEvent *de)
position is a backwards-compatible adapter for QDropEvent::position and pos functions.
Definition DeprecationHelper.h:47
bool isPlugin
Definition Util.cpp:41
#define N
Definition nseel-cfunc.c:36
#define false
Definition ordinals.h:83
png_uint_32 length
Definition png.c:2247
static void units(std::ostream &o, const char *u)
Definition ports.cpp:1772
@ kIsProgramChange
Definition ivsteditcontroller.h:69
const char * text
Definition swell-functions.h:167
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
struct HWND__ * HWND
Definition swell-types.h:210
int n
Definition crypt.c:458
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
void handler(int signal)
Definition fileio.c:1632
int flush(__G__ rawbuf, size, unshrink) __GDEF uch *rawbuf
int result
Definition process.c:1455
int flag
Definition unix.c:754
typedef int(UZ_EXP MsgFn)()
struct zdirent * file
Definition win32.c:1500
_WDL_CSTRING_PREFIX void INT_PTR count
Definition wdlcstring.h:263
_WDL_CSTRING_PREFIX void INT_PTR const char * format
Definition wdlcstring.h:263
#define const
Definition zconf.h:137