iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlug_include_in_plug_src.h
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5
6 See LICENSE.txt for more info.
7
8 ==============================================================================
9*/
10
11#pragma once
12
21#pragma mark - OS_WIN
22
23// clang-format off
24
25#if defined OS_WIN && !defined VST3C_API
26 HINSTANCE gHINSTANCE = 0;
27 #if defined(VST2_API) || defined(AAX_API) || defined(CLAP_API)
28 #ifdef __MINGW32__
29 extern "C"
30 #endif
31 BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD fdwReason, LPVOID res)
32 {
33 gHINSTANCE = hDllInst;
34 return true;
35 }
36 #endif
37
38 UINT(WINAPI *__GetDpiForWindow)(HWND);
39
40 float GetScaleForHWND(HWND hWnd)
41 {
42 if (!__GetDpiForWindow)
43 {
44 HINSTANCE h = LoadLibraryW(L"user32.dll");
45 if (h) *(void **)&__GetDpiForWindow = GetProcAddress(h, "GetDpiForWindow");
46
47 if (!__GetDpiForWindow)
48 return 1;
49 }
50
51 int dpi = __GetDpiForWindow(hWnd);
52
53 if (dpi != USER_DEFAULT_SCREEN_DPI)
54 {
55#if defined IGRAPHICS_QUANTISE_SCREENSCALE
56 return std::round(static_cast<float>(dpi) / USER_DEFAULT_SCREEN_DPI);
57#else
58 return static_cast<float>(dpi) / USER_DEFAULT_SCREEN_DPI;
59#endif
60 }
61
62 return 1;
63 }
64
65#endif
66
67#pragma mark - ** Global Functions and Defines **
68
69#pragma mark - VST2
70#if defined VST2_API
71 extern "C"
72 {
73 EXPORT void* VSTPluginMain(audioMasterCallback hostCallback)
74 {
75 using namespace iplug;
76
77 IPlugVST2* pPlug = iplug::MakePlug(iplug::InstanceInfo{hostCallback});
78
79 if (pPlug)
80 {
81 AEffect& aEffect = pPlug->GetAEffect();
82 pPlug->EnsureDefaultPreset();
83 aEffect.numPrograms = std::max(aEffect.numPrograms, 1); // some hosts don't like 0 presets
84 return &aEffect;
85 }
86 return 0;
87 }
88
89 EXPORT int main(int hostCallback)
90 {
91 audioMasterCallback callback = reinterpret_cast<audioMasterCallback>(static_cast<VstIntPtr>(hostCallback));
92 return static_cast<int>(reinterpret_cast<std::uintptr_t>(VSTPluginMain(callback)));
93 }
94 };
95#pragma mark - VST3 (All)
96#elif defined VST3_API || VST3C_API || defined VST3P_API
97 #include "public.sdk/source/main/pluginfactory.h"
98 #include "pluginterfaces/vst/ivstcomponent.h"
99 #include "pluginterfaces/vst/ivsteditcontroller.h"
100
101#if !defined VST3_PROCESSOR_UID && !defined VST3_CONTROLLER_UID
102#define VST3_PROCESSOR_UID 0xF2AEE70D, 0x00DE4F4E, PLUG_MFR_ID, PLUG_UNIQUE_ID
103#define VST3_CONTROLLER_UID 0xF2AEE70E, 0x00DE4F4F, PLUG_MFR_ID, PLUG_UNIQUE_ID
104#endif
105
106 #ifndef EFFECT_TYPE_VST3
107 #if PLUG_TYPE == 1
108 #define EFFECT_TYPE_VST3 kInstrumentSynth
109 #else
110 #define EFFECT_TYPE_VST3 kFx
111 #endif
112 #endif
113
114 #if defined VST3P_API || defined VST3_API
115 bool InitModule()
116 {
117 #ifdef OS_WIN
118 extern void* moduleHandle;
119 gHINSTANCE = (HINSTANCE) moduleHandle;
120 #endif
121 return true;
122 }
123
124 // called after library is unloaded
125 bool DeinitModule()
126 {
127 return true;
128 }
129 #endif
130 #pragma mark - VST3
131 #if defined VST3_API
132 static Steinberg::FUnknown* createInstance(void*)
133 {
134 return (Steinberg::Vst::IAudioProcessor*) iplug::MakePlug(iplug::InstanceInfo());
135 }
136
137 BEGIN_FACTORY_DEF(PLUG_MFR, PLUG_URL_STR, PLUG_EMAIL_STR)
138
139 DEF_CLASS2(INLINE_UID_FROM_FUID(FUID(VST3_PROCESSOR_UID)),
140 Steinberg::PClassInfo::kManyInstances, // cardinality
141 kVstAudioEffectClass, // the component category (don't change this)
142 PLUG_NAME, // plug-in name
143 Steinberg::Vst::kSimpleModeSupported, // means gui and plugin aren't split
144 VST3_SUBCATEGORY, // Subcategory for this plug-in
145 PLUG_VERSION_STR, // plug-in version
146 kVstVersionString, // the VST 3 SDK version (don't change - use define)
147 createInstance) // function pointer called to be instantiate
148
149 END_FACTORY
150 #pragma mark - VST3 Processor
151 #elif defined VST3P_API
152 static Steinberg::FUnknown* createProcessorInstance(void*)
153 {
154 return MakeProcessor();
155 }
156
157 static Steinberg::FUnknown* createControllerInstance(void*)
158 {
159 return MakeController();
160 }
161
162 BEGIN_FACTORY_DEF(PLUG_MFR, PLUG_URL_STR, PLUG_EMAIL_STR)
163
164 DEF_CLASS2 (INLINE_UID_FROM_FUID(FUID(VST3_PROCESSOR_UID)),
165 PClassInfo::kManyInstances, // cardinality
166 kVstAudioEffectClass, // the component category (do not changed this)
167 PLUG_NAME, // here the Plug-in name (to be changed)
168 Vst::kDistributable, // means component/controller can on different computers
169 VST3_SUBCATEGORY, // Subcategory for this Plug-in (to be changed)
170 PLUG_VERSION_STR, // Plug-in version (to be changed)
171 kVstVersionString, // the VST 3 SDK version (don't change - use define)
172 createProcessorInstance) // function pointer called to be instantiate
173
174 DEF_CLASS2(INLINE_UID_FROM_FUID(FUID(VST3_CONTROLLER_UID)),
175 PClassInfo::kManyInstances, // cardinality
176 kVstComponentControllerClass, // the Controller category (do not changed this)
177 PLUG_NAME " Controller", // controller name (could be the same than component name)
178 0, // not used here
179 "", // not used here
180 PLUG_VERSION_STR, // Plug-in version (to be changed)
181 kVstVersionString, // the VST 3 SDK version (don't change - use define)
182 createControllerInstance) // function pointer called to be instantiate
183
184 END_FACTORY
185 #endif
186#pragma mark - AUv2
187#elif defined AU_API
188 extern "C"
189 {
190 #ifndef AU_NO_COMPONENT_ENTRY
191 //Component Manager
192 EXPORT ComponentResult AUV2_ENTRY(ComponentParameters* pParams, void* pPlug)
193 {
194 return iplug::IPlugAU::IPlugAUEntry(pParams, pPlug);
195 }
196 #endif
197
198 //>10.7 SDK AUPlugin
199 EXPORT void* AUV2_FACTORY(const AudioComponentDescription* pInDesc)
200 {
201 return iplug::IPlugAUFactory<PLUG_CLASS_NAME, PLUG_DOES_MIDI_IN>::Factory(pInDesc);
202 }
203 };
204#pragma mark - WAM
205#elif defined WAM_API
206 extern "C"
207 {
208 EMSCRIPTEN_KEEPALIVE void* createModule()
209 {
210 Processor* pWAM = dynamic_cast<Processor*>(iplug::MakePlug(iplug::InstanceInfo()));
211 return (void*) pWAM;
212 }
213 }
214#pragma mark - WEB
215#elif defined WEB_API
216#include <memory>
217#include "config.h"
218 std::unique_ptr<iplug::IPlugWeb> gPlug;
219 extern void StartMainLoopTimer();
220
221 extern "C"
222 {
223 EMSCRIPTEN_KEEPALIVE void iplug_syncfs()
224 {
225 EM_ASM({
226 if(Module.syncdone == 1) {
227 Module.syncdone = 0;
228 FS.syncfs(false, function (err) {
229 assert(!err);
230 console.log("Synced to IDBFS...");
231 Module.syncdone = 1;
232 });
233 }
234 });
235 }
236
237 EMSCRIPTEN_KEEPALIVE void iplug_fsready()
238 {
239 gPlug = std::unique_ptr<iplug::IPlugWeb>(iplug::MakePlug(iplug::InstanceInfo()));
240 gPlug->SetHost("www", 0);
241 gPlug->OpenWindow(nullptr);
242 iplug_syncfs(); // plug in may initialise settings in constructor, write to persistent data after init
243 }
244 }
245
246 int main()
247 {
248 //create persistent data file system and synchronise
249 EM_ASM(
250 var name = '/' + UTF8ToString($0) + '_data';
251 FS.mkdir(name);
252 FS.mount(IDBFS, {}, name);
253
254 Module.syncdone = 0;
255 FS.syncfs(true, function (err) {
256 assert(!err);
257 console.log("Synced from IDBFS...");
258 Module.syncdone = 1;
259 ccall('iplug_fsready', 'v');
260 });
261 , PLUG_NAME);
262
263 StartMainLoopTimer();
264
265 // TODO: this code never runs, so when do we delete?!
266 gPlug = nullptr;
267
268 return 0;
269 }
270
271
272#pragma mark - Wasm UI
273#elif defined WASM_UI_API
274#include <memory>
275#include "config.h"
276
277 std::unique_ptr<iplug::IPlugWasmUI> gPlug;
278 extern void StartMainLoopTimer();
279
280 // Defined in IPlugWasmUI.cpp — replays any parent-window resize that
281 // arrived from JS before `gPlug` existed.
282 extern "C" void IPlugWasmUI_ApplyPendingParentWindowResize();
283
284 extern "C"
285 {
286 EMSCRIPTEN_KEEPALIVE void iplug_syncfs()
287 {
288 EM_ASM({
289 if(Module.syncdone == 1) {
290 Module.syncdone = 0;
291 FS.syncfs(false, function (err) {
292 assert(!err);
293 console.log("Synced to IDBFS...");
294 Module.syncdone = 1;
295 });
296 }
297 });
298 }
299
300 EMSCRIPTEN_KEEPALIVE void iplug_fsready()
301 {
302 gPlug = std::unique_ptr<iplug::IPlugWasmUI>(iplug::MakePlug(iplug::InstanceInfo()));
303 gPlug->SetHost("www", 0);
304 gPlug->OpenWindow(nullptr);
305 // IDBFS sync ran async, so the JS bundle's initial
306 // OnParentWindowResize likely already fired and was buffered.
307 // Apply it now, before the first frame is drawn.
308 IPlugWasmUI_ApplyPendingParentWindowResize();
309 iplug_syncfs();
310 }
311 }
312
313 int main()
314 {
315 // Create persistent data file system and synchronize
316 EM_ASM(
317 var name = '/' + UTF8ToString($0) + '_data';
318 FS.mkdir(name);
319 FS.mount(IDBFS, {}, name);
320
321 Module.syncdone = 0;
322 FS.syncfs(true, function (err) {
323 assert(!err);
324 console.log("Synced from IDBFS...");
325 Module.syncdone = 1;
326 ccall('iplug_fsready', 'v');
327 });
328 , PLUG_NAME);
329
330 StartMainLoopTimer();
331
332 gPlug = nullptr;
333
334 return 0;
335 }
336
337#pragma mark - CLAP
338#elif defined CLAP_API
339
340// Make sure optional fields are defined
341
342#ifndef CLAP_MANUAL_URL
343#define CLAP_MANUAL_URL ""
344#endif
345#ifndef CLAP_SUPPORT_URL
346#define CLAP_SUPPORT_URL ""
347#endif
348#ifndef CLAP_DESCRIPTION
349#define CLAP_DESCRIPTION ""
350#endif
351#ifndef CLAP_FEATURES
352 #if PLUG_TYPE==0
353 #define CLAP_FEATURES CLAP_PLUGIN_FEATURE_AUDIO_EFFECT
354 #elif PLUG_TYPE==1
355 #define CLAP_FEATURES CLAP_PLUGIN_FEATURE_INSTRUMENT
356 #elif PLUG_TYPE==2
357 #define CLAP_FEATURES CLAP_PLUGIN_FEATURE_NOTE_EFFECT
358 #endif
359#endif
360
361std::string gPluginPath;
362std::unique_ptr<clap_plugin_descriptor> gPluginDesc;
363
364static bool clap_init(const char* pluginPath)
365{
366 // Init globals
367
368 gPluginPath = pluginPath;
369 gPluginDesc = std::unique_ptr<clap_plugin_descriptor>(new clap_plugin_descriptor());
370
371 // Init the descriptor
372
373 gPluginDesc->clap_version = CLAP_VERSION;
374
375 gPluginDesc->id = BUNDLE_DOMAIN "." BUNDLE_MFR "." BUNDLE_NAME;
376 gPluginDesc->name = PLUG_NAME;
377 gPluginDesc->vendor = PLUG_MFR;
378 gPluginDesc->url = PLUG_URL_STR;
379
380 gPluginDesc->manual_url = CLAP_MANUAL_URL;
381 gPluginDesc->version = PLUG_VERSION_STR;
382 gPluginDesc->support_url = CLAP_SUPPORT_URL;
383 gPluginDesc->description = CLAP_DESCRIPTION;
384
385 static const char *clap_features[] = { CLAP_FEATURES, NULL };
386 gPluginDesc->features = clap_features;
387
388 return true;
389}
390
391static void clap_deinit(void)
392{
393 gPluginPath.clear();
394 gPluginDesc = nullptr;
395}
396
397static uint32_t clap_get_plugin_count(const clap_plugin_factory_t *factory)
398{
399 return 1;
400}
401
402static const clap_plugin_descriptor* clap_get_plugin_descriptor(const clap_plugin_factory_t *factory, uint32_t index)
403{
404 if (!index)
405 return gPluginDesc.get();
406
407 return nullptr;
408}
409
410static const clap_plugin* clap_create_plugin(const clap_plugin_factory_t *factory, const clap_host* host, const char* plugin_id)
411{
412 if (!strcmp(gPluginDesc->id, plugin_id))
413 {
414 iplug::IPlugCLAP* pPlug = iplug::MakePlug(iplug::InstanceInfo{gPluginDesc.get(), host});
415 return pPlug->clapPlugin();
416 }
417
418 return nullptr;
419}
420
421CLAP_EXPORT const clap_plugin_factory_t clap_factory = {
422 clap_get_plugin_count,
423 clap_get_plugin_descriptor,
424 clap_create_plugin,
425};
426
427const void *clap_get_factory(const char *factory_id)
428{
429 if (!::strcmp(factory_id, CLAP_PLUGIN_FACTORY_ID))
430 return &clap_factory;
431
432 return nullptr;
433}
434
435CLAP_EXPORT const clap_plugin_entry_t clap_entry = {
436 CLAP_VERSION,
437 clap_init,
438 clap_deinit,
439 clap_get_factory,
440};
441
442#elif defined AUv3_API || defined AAX_API || defined APP_API || defined WAM_API || defined WEB_API || defined WASM_DSP_API || defined WASM_UI_API
443// Nothing to do here
444#else
445 #error "No API defined!"
446#endif
447
448#pragma mark - ** Instantiation **
449
450BEGIN_IPLUG_NAMESPACE
451
452#pragma mark -
453#pragma mark VST2, VST3, AAX, AUv3, APP, WAM, WEB, CLAP
454
455#if defined VST2_API || defined VST3_API || defined AAX_API || defined AUv3_API || defined APP_API || defined WAM_API || defined WEB_API || defined WASM_DSP_API || defined WASM_UI_API || defined CLAP_API
456
457Plugin* MakePlug(const iplug::InstanceInfo& info)
458{
459 // From VST3 - is this necessary?
460 static WDL_Mutex sMutex;
461 WDL_MutexLock lock(&sMutex);
462
463 return new PLUG_CLASS_NAME(info);
464}
465
466#pragma mark - AUv2
467#elif defined AU_API
468
469Plugin* MakePlug(void* pMemory)
470{
471 iplug::InstanceInfo info;
472 info.mCocoaViewFactoryClassName.Set(AUV2_VIEW_CLASS_STR);
473
474 if (pMemory)
475 return new(pMemory) PLUG_CLASS_NAME(info);
476 else
477 return new PLUG_CLASS_NAME(info);
478}
479
480#pragma mark - VST3 Controller
481#elif defined VST3C_API
482
483Steinberg::FUnknown* MakeController()
484{
485 static WDL_Mutex sMutex;
486 WDL_MutexLock lock(&sMutex);
487 iplug::IPlugVST3Controller::InstanceInfo info;
488 info.mOtherGUID = Steinberg::FUID(VST3_PROCESSOR_UID);
489 // If you are trying to build a distributed VST3 plug-in and you hit an error here like "no matching constructor..." or
490 // "error: unknown type name 'VST3Controller'", you need to replace all instances of the name of your plug-in class (e.g. IPlugEffect)
491 // with the macro PLUG_CLASS_NAME, as defined in your plug-ins config.h, so IPlugEffect::IPlugEffect() {} becomes PLUG_CLASS_NAME::PLUG_CLASS_NAME().
492 return static_cast<Steinberg::Vst::IEditController*>(new PLUG_CLASS_NAME(info));
493}
494
495#pragma mark - VST3 Processor
496#elif defined VST3P_API
497
498Steinberg::FUnknown* MakeProcessor()
499{
500 static WDL_Mutex sMutex;
501 WDL_MutexLock lock(&sMutex);
502 iplug::IPlugVST3Processor::InstanceInfo info;
503 info.mOtherGUID = Steinberg::FUID(VST3_CONTROLLER_UID);
504 return static_cast<Steinberg::Vst::IAudioProcessor*>(new PLUG_CLASS_NAME(info));
505}
506#else
507#error "No API defined!"
508#endif
509
510#pragma mark - ** Config Utility **
511
512static Config MakeConfig(int nParams, int nPresets)
513{
514 return Config(nParams, nPresets, PLUG_CHANNEL_IO, PLUG_NAME, PLUG_NAME, PLUG_MFR, PLUG_VERSION_HEX, PLUG_UNIQUE_ID, PLUG_MFR_ID, PLUG_LATENCY, PLUG_DOES_MIDI_IN, PLUG_DOES_MIDI_OUT, PLUG_DOES_MPE, PLUG_DOES_STATE_CHUNKS, PLUG_TYPE, PLUG_HAS_UI, PLUG_WIDTH, PLUG_HEIGHT, PLUG_HOST_RESIZE, PLUG_MIN_WIDTH, PLUG_MAX_WIDTH, PLUG_MIN_HEIGHT, PLUG_MAX_HEIGHT, BUNDLE_ID, APP_GROUP_ID); // TODO: Product Name?
515}
516
517END_IPLUG_NAMESPACE
518
519/*
520 #if defined _DEBUG
521 #define PLUG_NAME APPEND_TIMESTAMP(PLUG_NAME " DEBUG")
522 #elif defined TRACER_BUILD
523 #define PLUG_NAME APPEND_TIMESTAMP(PLUG_NAME " TRACER")
524 #elif defined TIMESTAMP_PLUG_NAME
525 #pragma REMINDER("plug name is timestamped")
526 #define PLUG_NAME APPEND_TIMESTAMP(PLUG_NAME)
527 #else
528 #define PLUG_NAME PLUG_NAME
529 #endif
530 */
531
532#if !defined NO_IGRAPHICS && !defined VST3P_API
533#include "IGraphics_include_in_plug_src.h"
534#endif
535
536// clang-format on
VST2.4 API base class for an IPlug plug-in.
Definition: IPlugVST2.h:36
void EnsureDefaultPreset()
[VST2 only] Called to fill uninitialzed presets