1 /*
2  * Carla Native Plugin API (C++)
3  * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16  */
17 
18 #ifndef CARLA_NATIVE_HPP_INCLUDED
19 #define CARLA_NATIVE_HPP_INCLUDED
20 
21 #include "CarlaNative.h"
22 #include "CarlaMIDI.h"
23 #include "CarlaJuceUtils.hpp"
24 
25 /*!
26  * @defgroup CarlaNativeAPI Carla Native API
27  * @{
28  */
29 
30 // --------------------------------------------------------------------------------------------------------------------
31 // Native Plugin Class
32 
33 class NativePluginClass
34 {
35 public:
NativePluginClass(const NativeHostDescriptor * const host)36     NativePluginClass(const NativeHostDescriptor* const host)
37         : pHost(host)
38     {
39         CARLA_SAFE_ASSERT(host != nullptr);
40     }
41 
~NativePluginClass()42     virtual ~NativePluginClass() {}
43 
44 protected:
45     // -------------------------------------------------------------------
46     // Host calls
47 
getHostHandle() const48     const NativeHostDescriptor* getHostHandle() const noexcept
49     {
50         return pHost;
51     }
52 
getResourceDir() const53     const char* getResourceDir() const noexcept
54     {
55         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
56 
57         return pHost->resourceDir;
58     }
59 
getUiName() const60     const char* getUiName() const noexcept
61     {
62         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
63 
64         return pHost->uiName;
65     }
66 
getUiParentId() const67     uintptr_t getUiParentId() const noexcept
68     {
69         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
70 
71         return pHost->uiParentId;
72     }
73 
getBufferSize() const74     uint32_t getBufferSize() const
75     {
76         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
77 
78         return pHost->get_buffer_size(pHost->handle);
79     }
80 
getSampleRate() const81     double getSampleRate() const
82     {
83         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0.0);
84 
85         return pHost->get_sample_rate(pHost->handle);
86     }
87 
isOffline() const88     bool isOffline() const
89     {
90         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, false);
91 
92         return pHost->is_offline(pHost->handle);
93     }
94 
getTimeInfo() const95     const NativeTimeInfo* getTimeInfo() const
96     {
97         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
98 
99         return pHost->get_time_info(pHost->handle);
100     }
101 
writeMidiEvent(const NativeMidiEvent * const event) const102     void writeMidiEvent(const NativeMidiEvent* const event) const
103     {
104         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
105 
106         pHost->write_midi_event(pHost->handle, event);
107     }
108 
uiParameterChanged(const uint32_t index,const float value) const109     void uiParameterChanged(const uint32_t index, const float value) const
110     {
111         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
112 
113         pHost->ui_parameter_changed(pHost->handle, index, value);
114     }
115 
uiParameterTouch(const uint32_t index,const bool touch) const116     void uiParameterTouch(const uint32_t index, const bool touch) const
117     {
118         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
119 
120         pHost->dispatcher(pHost->handle,
121                           NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER,
122                           static_cast<int32_t>(index),
123                           touch ? 1 : 0,
124                           nullptr, 0.0f);
125     }
126 
uiMidiProgramChanged(const uint8_t channel,const uint32_t bank,const uint32_t program) const127     void uiMidiProgramChanged(const uint8_t channel, const uint32_t bank, const uint32_t program) const
128     {
129         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
130 
131         pHost->ui_midi_program_changed(pHost->handle, channel, bank, program);
132     }
133 
uiCustomDataChanged(const char * const key,const char * const value) const134     void uiCustomDataChanged(const char* const key, const char* const value) const
135     {
136         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
137 
138         pHost->ui_custom_data_changed(pHost->handle, key, value);
139     }
140 
uiClosed() const141     void uiClosed() const
142     {
143         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
144 
145         pHost->ui_closed(pHost->handle);
146     }
147 
uiOpenFile(const bool isDir,const char * const title,const char * const filter) const148     const char* uiOpenFile(const bool isDir, const char* const title, const char* const filter) const
149     {
150         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
151 
152         return pHost->ui_open_file(pHost->handle, isDir, title, filter);
153     }
154 
uiSaveFile(const bool isDir,const char * const title,const char * const filter) const155     const char* uiSaveFile(const bool isDir, const char* const title, const char* const filter) const
156     {
157         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
158 
159         return pHost->ui_save_file(pHost->handle, isDir, title, filter);
160     }
161 
162     // -------------------------------------------------------------------
163     // Host dispatcher calls
164 
hostUpdateParameter(const int32_t index) const165     void hostUpdateParameter(const int32_t index) const
166     {
167         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
168 
169         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_PARAMETER, index, 0, nullptr, 0.0f);
170     }
171 
hostUpdateAllParameters() const172     void hostUpdateAllParameters() const
173     {
174         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
175 
176         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_PARAMETER, -1, 0, nullptr, 0.0f);
177     }
178 
hostUpdateMidiProgram(const int32_t index,const intptr_t channel=0) const179     void hostUpdateMidiProgram(const int32_t index, const intptr_t channel = 0) const
180     {
181         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
182 
183         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM, index, channel, nullptr, 0.0f);
184     }
185 
hostUpdateAllMidiPrograms(const intptr_t channel=0) const186     void hostUpdateAllMidiPrograms(const intptr_t channel = 0) const
187     {
188         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
189 
190         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM, -1, channel, nullptr, 0.0f);
191     }
192 
hostReloadParameters() const193     void hostReloadParameters() const
194     {
195         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
196 
197         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f);
198     }
199 
hostReloadMidiPrograms() const200     void hostReloadMidiPrograms() const
201     {
202         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
203 
204         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS, 0, 0, nullptr, 0.0f);
205     }
206 
hostReloadAll() const207     void hostReloadAll() const
208     {
209         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
210 
211         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
212     }
213 
hostUiUnavailable() const214     void hostUiUnavailable() const
215     {
216         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
217 
218         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
219     }
220 
hostGiveIdle() const221     void hostGiveIdle() const
222     {
223         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
224 
225         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f);
226     }
227 
hostRequestIdle() const228     bool hostRequestIdle() const
229     {
230         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
231 
232         return pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_REQUEST_IDLE, 0, 0, nullptr, 0.0f) == 1;
233     }
234 
hostQueueDrawInlineDisplay()235     bool hostQueueDrawInlineDisplay()
236     {
237         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
238 
239         return pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY, 0, 0, nullptr, 0.0f) == 1;
240     }
241 
hostGetFilePath(const char * const filetype) const242     const char* hostGetFilePath(const char* const filetype) const
243     {
244         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
245 
246         return (const char*)(uintptr_t)pHost->dispatcher(pHost->handle,
247                                                          NATIVE_HOST_OPCODE_GET_FILE_PATH,
248                                                          0, 0,
249                                                          (void*)const_cast<char*>(filetype),
250                                                          0.0f);
251     }
252 
hostSendPreviewBufferData(const char type,const uint32_t size,const void * const buffer)253     void hostSendPreviewBufferData(const char type, const uint32_t size, const void* const buffer)
254     {
255         CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
256 
257         pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA, type, size, const_cast<void*>(buffer), 0.0f);
258     }
259 
260     // -------------------------------------------------------------------
261     // Plugin parameter calls
262 
getParameterCount() const263     virtual uint32_t getParameterCount() const
264     {
265         return 0;
266     }
267 
getParameterInfo(const uint32_t index) const268     virtual const NativeParameter* getParameterInfo(const uint32_t index) const
269     {
270         CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
271         return nullptr;
272     }
273 
getParameterValue(const uint32_t index) const274     virtual float getParameterValue(const uint32_t index) const
275     {
276         CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
277         return 0.0f;
278     }
279 
280     // -------------------------------------------------------------------
281     // Plugin midi-program calls
282 
getMidiProgramCount() const283     virtual uint32_t getMidiProgramCount() const
284     {
285         return 0;
286     }
287 
getMidiProgramInfo(const uint32_t index) const288     virtual const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
289     {
290         CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
291         return nullptr;
292     }
293 
294     // -------------------------------------------------------------------
295     // Plugin state calls
296 
setParameterValue(const uint32_t index,const float value)297     virtual void setParameterValue(const uint32_t index, const float value)
298     {
299         CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
300         return;
301 
302         // unused
303         (void)value;
304     }
305 
setMidiProgram(const uint8_t channel,const uint32_t bank,const uint32_t program)306     virtual void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
307     {
308         CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
309         return;
310 
311         // unused
312         (void)bank; (void)program;
313     }
314 
setCustomData(const char * const key,const char * const value)315     virtual void setCustomData(const char* const key, const char* const value)
316     {
317         CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
318         CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
319     }
320 
321     // -------------------------------------------------------------------
322     // Plugin process calls
323 
activate()324     virtual void activate() {}
325 
deactivate()326     virtual void deactivate() {}
327 
328     virtual void process(const float* const* inBuffer, float** outBuffer, uint32_t frames,
329                          const NativeMidiEvent* midiEvents, uint32_t midiEventCount) = 0;
330 
331     // -------------------------------------------------------------------
332     // Plugin UI calls
333 
uiShow(const bool show)334     virtual void uiShow(const bool show)
335     {
336         return;
337 
338         // unused
339         (void)show;
340     }
341 
uiIdle()342     virtual void uiIdle()
343     {
344     }
345 
uiSetParameterValue(const uint32_t index,const float value)346     virtual void uiSetParameterValue(const uint32_t index, const float value)
347     {
348         CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
349         return;
350 
351         // unused
352         (void)value;
353     }
354 
uiSetMidiProgram(const uint8_t channel,const uint32_t bank,const uint32_t program)355     virtual void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
356     {
357         CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
358         return;
359 
360         // unused
361         (void)bank; (void)program;
362     }
363 
uiSetCustomData(const char * const key,const char * const value)364     virtual void uiSetCustomData(const char* const key, const char* const value)
365     {
366         CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
367         CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
368     }
369 
370     // -------------------------------------------------------------------
371     // Plugin state calls
372 
getState() const373     virtual char* getState() const
374     {
375         return nullptr;
376     }
377 
setState(const char * const data)378     virtual void setState(const char* const data)
379     {
380         CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
381     }
382 
383     // -------------------------------------------------------------------
384     // Plugin dispatcher calls
385 
bufferSizeChanged(const uint32_t bufferSize)386     virtual void bufferSizeChanged(const uint32_t bufferSize)
387     {
388         return;
389 
390         // unused
391         (void)bufferSize;
392     }
393 
sampleRateChanged(const double sampleRate)394     virtual void sampleRateChanged(const double sampleRate)
395     {
396         return;
397 
398         // unused
399         (void)sampleRate;
400     }
401 
offlineChanged(const bool offline)402     virtual void offlineChanged(const bool offline)
403     {
404         return;
405 
406         // unused
407         (void)offline;
408     }
409 
uiNameChanged(const char * const uiName)410     virtual void uiNameChanged(const char* const uiName)
411     {
412         CARLA_SAFE_ASSERT_RETURN(uiName != nullptr && uiName[0] != '\0',);
413     }
414 
uiMIDIEvent(uint8_t size,const uint8_t data[])415     virtual bool uiMIDIEvent(uint8_t size, const uint8_t data[])
416     {
417         return false;
418 
419         // unused
420         (void)size;
421         (void)data;
422     }
423 
renderInlineDisplay(const uint32_t width,const uint32_t height)424     virtual const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t width, const uint32_t height)
425     {
426         CARLA_SAFE_ASSERT_RETURN(width > 0 && height > 0, nullptr);
427 
428         return nullptr;
429     }
430 
idle()431     virtual void idle() {}
432 
433     // -------------------------------------------------------------------
434 
435 private:
436     const NativeHostDescriptor* const pHost;
437 
438     // -------------------------------------------------------------------
439 
440 #ifndef DOXYGEN
441 public:
442     #define handlePtr ((NativePluginClass*)handle)
443 
_get_parameter_count(NativePluginHandle handle)444     static uint32_t _get_parameter_count(NativePluginHandle handle)
445     {
446         return handlePtr->getParameterCount();
447     }
448 
_get_parameter_info(NativePluginHandle handle,uint32_t index)449     static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
450     {
451         return handlePtr->getParameterInfo(index);
452     }
453 
_get_parameter_value(NativePluginHandle handle,uint32_t index)454     static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
455     {
456         return handlePtr->getParameterValue(index);
457     }
458 
_get_midi_program_count(NativePluginHandle handle)459     static uint32_t _get_midi_program_count(NativePluginHandle handle)
460     {
461         return handlePtr->getMidiProgramCount();
462     }
463 
_get_midi_program_info(NativePluginHandle handle,uint32_t index)464     static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
465     {
466         return handlePtr->getMidiProgramInfo(index);
467     }
468 
_set_parameter_value(NativePluginHandle handle,uint32_t index,float value)469     static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
470     {
471         handlePtr->setParameterValue(index, value);
472     }
473 
_set_midi_program(NativePluginHandle handle,uint8_t channel,uint32_t bank,uint32_t program)474     static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
475     {
476         handlePtr->setMidiProgram(channel, bank, program);
477     }
478 
_set_custom_data(NativePluginHandle handle,const char * key,const char * value)479     static void _set_custom_data(NativePluginHandle handle, const char* key, const char* value)
480     {
481         handlePtr->setCustomData(key, value);
482     }
483 
_ui_show(NativePluginHandle handle,bool show)484     static void _ui_show(NativePluginHandle handle, bool show)
485     {
486         handlePtr->uiShow(show);
487     }
488 
_ui_idle(NativePluginHandle handle)489     static void _ui_idle(NativePluginHandle handle)
490     {
491         handlePtr->uiIdle();
492     }
493 
_ui_set_parameter_value(NativePluginHandle handle,uint32_t index,float value)494     static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
495     {
496         handlePtr->uiSetParameterValue(index, value);
497     }
498 
_ui_set_midi_program(NativePluginHandle handle,uint8_t channel,uint32_t bank,uint32_t program)499     static void _ui_set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
500     {
501         handlePtr->uiSetMidiProgram(channel, bank, program);
502     }
503 
_ui_set_custom_data(NativePluginHandle handle,const char * key,const char * value)504     static void _ui_set_custom_data(NativePluginHandle handle, const char* key, const char* value)
505     {
506         handlePtr->uiSetCustomData(key, value);
507     }
508 
_activate(NativePluginHandle handle)509     static void _activate(NativePluginHandle handle)
510     {
511         handlePtr->activate();
512     }
513 
_deactivate(NativePluginHandle handle)514     static void _deactivate(NativePluginHandle handle)
515     {
516         handlePtr->deactivate();
517     }
518 
519     // FIXME for v3.0, use const for the input buffer
_process(NativePluginHandle handle,float ** inBuffer,float ** outBuffer,const uint32_t frames,const NativeMidiEvent * midiEvents,uint32_t midiEventCount)520     static void _process(NativePluginHandle handle,
521                          float** inBuffer, float** outBuffer, const uint32_t frames,
522                          const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
523     {
524         handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
525     }
526 
_get_state(NativePluginHandle handle)527     static char* _get_state(NativePluginHandle handle)
528     {
529         return handlePtr->getState();
530     }
531 
_set_state(NativePluginHandle handle,const char * data)532     static void _set_state(NativePluginHandle handle, const char* data)
533     {
534         handlePtr->setState(data);
535     }
536 
_dispatcher(NativePluginHandle handle,NativePluginDispatcherOpcode opcode,int32_t index,intptr_t value,void * ptr,float opt)537     static intptr_t _dispatcher(NativePluginHandle handle,
538                                 NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
539     {
540         switch(opcode)
541         {
542         case NATIVE_PLUGIN_OPCODE_NULL:
543             return 0;
544         case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
545             CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
546             handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
547             return 0;
548         case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
549             CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
550             handlePtr->sampleRateChanged(static_cast<double>(opt));
551             return 0;
552         case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED:
553             handlePtr->offlineChanged(value != 0);
554             return 0;
555         case NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED:
556             CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
557             handlePtr->uiNameChanged(static_cast<const char*>(ptr));
558             return 0;
559         case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE:
560             return 0;
561         case NATIVE_PLUGIN_OPCODE_IDLE:
562             handlePtr->idle();
563             return 0;
564         case NATIVE_PLUGIN_OPCODE_UI_MIDI_EVENT:
565             CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < UINT8_MAX, 0);
566             CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
567             return handlePtr->uiMIDIEvent(static_cast<uint8_t>(index),
568                                           static_cast<uint8_t*>(ptr));
569         case NATIVE_PLUGIN_OPCODE_HOST_USES_EMBED:
570             return 0;
571         }
572 
573         return 0;
574 
575         // unused
576         (void)index;
577     }
578 
_render_inline_display(NativePluginHandle handle,uint32_t width,uint32_t height)579     static const NativeInlineDisplayImageSurface* _render_inline_display(NativePluginHandle handle, uint32_t width, uint32_t height)
580     {
581         return handlePtr->renderInlineDisplay(width, height);
582     }
583 
584     #undef handlePtr
585 
586     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginClass)
587 #endif
588 };
589 
590 /**@}*/
591 
592 // --------------------------------------------------------------------------------------------------------------------
593 // -Weffc++ compat ext widget
594 
595 extern "C" {
596 
597 typedef struct _NativeInlineDisplayImageSurfaceCompat {
598     unsigned char* data;
599     int width, height, stride;
600     size_t dataSize;
601 
_NativeInlineDisplayImageSurfaceCompat_NativeInlineDisplayImageSurfaceCompat602   _NativeInlineDisplayImageSurfaceCompat() noexcept
603       : data(nullptr), width(0), height(0), stride(0), dataSize(0) {}
604 
605 } NativeInlineDisplayImageSurfaceCompat;
606 
607 }
608 
609 // --------------------------------------------------------------------------------------------------------------------
610 
611 #define PluginClassEND(ClassName)                                            \
612 public:                                                                      \
613     static NativePluginHandle _instantiate(const NativeHostDescriptor* host) \
614     {                                                                        \
615         return (host != nullptr) ? new ClassName(host) : nullptr;            \
616     }                                                                        \
617     static void _cleanup(NativePluginHandle handle)                          \
618     {                                                                        \
619         delete (ClassName*)handle;                                           \
620     }
621 
622 #define PluginDescriptorFILL(ClassName) \
623     ClassName::_instantiate,            \
624     ClassName::_cleanup,                \
625     ClassName::_get_parameter_count,    \
626     ClassName::_get_parameter_info,     \
627     ClassName::_get_parameter_value,    \
628     ClassName::_get_midi_program_count, \
629     ClassName::_get_midi_program_info,  \
630     ClassName::_set_parameter_value,    \
631     ClassName::_set_midi_program,       \
632     ClassName::_set_custom_data,        \
633     ClassName::_ui_show,                \
634     ClassName::_ui_idle,                \
635     ClassName::_ui_set_parameter_value, \
636     ClassName::_ui_set_midi_program,    \
637     ClassName::_ui_set_custom_data,     \
638     ClassName::_activate,               \
639     ClassName::_deactivate,             \
640     ClassName::_process,                \
641     ClassName::_get_state,              \
642     ClassName::_set_state,              \
643     ClassName::_dispatcher,             \
644     ClassName::_render_inline_display,  \
645     0, 0, nullptr, nullptr, 0, 0
646 
647 // --------------------------------------------------------------------------------------------------------------------
648 
649 #endif // CARLA_NATIVE_HPP_INCLUDED
650