2 * Carla Native Plugin API (C++)
3 * Copyright (C) 2012-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_NATIVE_HPP_INCLUDED
19 #define CARLA_NATIVE_HPP_INCLUDED
21 #include "CarlaNative.h"
22 #include "CarlaMIDI.h"
23 #include "CarlaJuceUtils.hpp"
26 * @defgroup CarlaNativeAPI Carla Native API
30 // --------------------------------------------------------------------------------------------------------------------
31 // Native Plugin Class
33 class NativePluginClass
36 NativePluginClass(const NativeHostDescriptor
* const host
)
39 CARLA_SAFE_ASSERT(host
!= nullptr);
42 virtual ~NativePluginClass() {}
45 // -------------------------------------------------------------------
48 const NativeHostDescriptor
* getHostHandle() const noexcept
53 const char* getResourceDir() const noexcept
55 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
57 return pHost
->resourceDir
;
60 const char* getUiName() const noexcept
62 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
67 uintptr_t getUiParentId() const noexcept
69 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, 0);
71 return pHost
->uiParentId
;
74 uint32_t getBufferSize() const
76 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, 0);
78 return pHost
->get_buffer_size(pHost
->handle
);
81 double getSampleRate() const
83 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, 0.0);
85 return pHost
->get_sample_rate(pHost
->handle
);
88 bool isOffline() const
90 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, false);
92 return pHost
->is_offline(pHost
->handle
);
95 const NativeTimeInfo
* getTimeInfo() const
97 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
99 return pHost
->get_time_info(pHost
->handle
);
102 void writeMidiEvent(const NativeMidiEvent
* const event
) const
104 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
106 pHost
->write_midi_event(pHost
->handle
, event
);
109 void uiParameterChanged(const uint32_t index
, const float value
) const
111 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
113 pHost
->ui_parameter_changed(pHost
->handle
, index
, value
);
116 void uiParameterTouch(const uint32_t index
, const bool touch
) const
118 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
120 pHost
->dispatcher(pHost
->handle
,
121 NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER
,
122 static_cast<int32_t>(index
),
127 void uiMidiProgramChanged(const uint8_t channel
, const uint32_t bank
, const uint32_t program
) const
129 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
131 pHost
->ui_midi_program_changed(pHost
->handle
, channel
, bank
, program
);
134 void uiCustomDataChanged(const char* const key
, const char* const value
) const
136 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
138 pHost
->ui_custom_data_changed(pHost
->handle
, key
, value
);
141 void uiClosed() const
143 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
145 pHost
->ui_closed(pHost
->handle
);
148 const char* uiOpenFile(const bool isDir
, const char* const title
, const char* const filter
) const
150 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
152 return pHost
->ui_open_file(pHost
->handle
, isDir
, title
, filter
);
155 const char* uiSaveFile(const bool isDir
, const char* const title
, const char* const filter
) const
157 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
159 return pHost
->ui_save_file(pHost
->handle
, isDir
, title
, filter
);
162 // -------------------------------------------------------------------
163 // Host dispatcher calls
165 void hostUpdateParameter(const int32_t index
) const
167 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
169 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_UPDATE_PARAMETER
, index
, 0, nullptr, 0.0f
);
172 void hostUpdateAllParameters() const
174 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
176 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_UPDATE_PARAMETER
, -1, 0, nullptr, 0.0f
);
179 void hostUpdateMidiProgram(const int32_t index
, const intptr_t channel
= 0) const
181 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
183 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM
, index
, channel
, nullptr, 0.0f
);
186 void hostUpdateAllMidiPrograms(const intptr_t channel
= 0) const
188 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
190 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM
, -1, channel
, nullptr, 0.0f
);
193 void hostReloadParameters() const
195 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
197 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_RELOAD_PARAMETERS
, 0, 0, nullptr, 0.0f
);
200 void hostReloadMidiPrograms() const
202 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
204 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS
, 0, 0, nullptr, 0.0f
);
207 void hostReloadAll() const
209 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
211 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_RELOAD_ALL
, 0, 0, nullptr, 0.0f
);
214 void hostUiUnavailable() const
216 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
218 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_UI_UNAVAILABLE
, 0, 0, nullptr, 0.0f
);
221 void hostGiveIdle() const
223 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
225 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_HOST_IDLE
, 0, 0, nullptr, 0.0f
);
228 bool hostRequestIdle() const
230 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, 0);
232 return pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_REQUEST_IDLE
, 0, 0, nullptr, 0.0f
) == 1;
235 bool hostQueueDrawInlineDisplay()
237 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, 0);
239 return pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY
, 0, 0, nullptr, 0.0f
) == 1;
242 const char* hostGetFilePath(const char* const filetype
) const
244 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr, nullptr);
246 return (const char*)(uintptr_t)pHost
->dispatcher(pHost
->handle
,
247 NATIVE_HOST_OPCODE_GET_FILE_PATH
,
249 (void*)const_cast<char*>(filetype
),
253 void hostSendPreviewBufferData(const char type
, const uint32_t size
, const void* const buffer
)
255 CARLA_SAFE_ASSERT_RETURN(pHost
!= nullptr,);
257 pHost
->dispatcher(pHost
->handle
, NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA
, type
, size
, const_cast<void*>(buffer
), 0.0f
);
260 // -------------------------------------------------------------------
261 // Plugin parameter calls
263 virtual uint32_t getParameterCount() const
268 virtual const NativeParameter
* getParameterInfo(const uint32_t index
) const
270 CARLA_SAFE_ASSERT_RETURN(index
< getParameterCount(), nullptr);
274 virtual float getParameterValue(const uint32_t index
) const
276 CARLA_SAFE_ASSERT_RETURN(index
< getParameterCount(), 0.0f
);
280 // -------------------------------------------------------------------
281 // Plugin midi-program calls
283 virtual uint32_t getMidiProgramCount() const
288 virtual const NativeMidiProgram
* getMidiProgramInfo(const uint32_t index
) const
290 CARLA_SAFE_ASSERT_RETURN(index
< getMidiProgramCount(), nullptr);
294 // -------------------------------------------------------------------
295 // Plugin state calls
297 virtual void setParameterValue(const uint32_t index
, const float value
)
299 CARLA_SAFE_ASSERT_RETURN(index
< getParameterCount(),);
306 virtual void setMidiProgram(const uint8_t channel
, const uint32_t bank
, const uint32_t program
)
308 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
312 (void)bank
; (void)program
;
315 virtual void setCustomData(const char* const key
, const char* const value
)
317 CARLA_SAFE_ASSERT_RETURN(key
!= nullptr && key
[0] != '\0',);
318 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr,);
321 // -------------------------------------------------------------------
322 // Plugin process calls
324 virtual void activate() {}
326 virtual void deactivate() {}
328 virtual void process(const float* const* inBuffer
, float** outBuffer
, uint32_t frames
,
329 const NativeMidiEvent
* midiEvents
, uint32_t midiEventCount
) = 0;
331 // -------------------------------------------------------------------
334 virtual void uiShow(const bool show
)
342 virtual void uiIdle()
346 virtual void uiSetParameterValue(const uint32_t index
, const float value
)
348 CARLA_SAFE_ASSERT_RETURN(index
< getParameterCount(),);
355 virtual void uiSetMidiProgram(const uint8_t channel
, const uint32_t bank
, const uint32_t program
)
357 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
361 (void)bank
; (void)program
;
364 virtual void uiSetCustomData(const char* const key
, const char* const value
)
366 CARLA_SAFE_ASSERT_RETURN(key
!= nullptr && key
[0] != '\0',);
367 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr,);
370 // -------------------------------------------------------------------
371 // Plugin state calls
373 virtual char* getState() const
378 virtual void setState(const char* const data
)
380 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr,);
383 // -------------------------------------------------------------------
384 // Plugin dispatcher calls
386 virtual void bufferSizeChanged(const uint32_t bufferSize
)
394 virtual void sampleRateChanged(const double sampleRate
)
402 virtual void offlineChanged(const bool offline
)
410 virtual void uiNameChanged(const char* const uiName
)
412 CARLA_SAFE_ASSERT_RETURN(uiName
!= nullptr && uiName
[0] != '\0',);
415 virtual bool uiMIDIEvent(uint8_t size
, const uint8_t data
[])
424 virtual const NativeInlineDisplayImageSurface
* renderInlineDisplay(const uint32_t width
, const uint32_t height
)
426 CARLA_SAFE_ASSERT_RETURN(width
> 0 && height
> 0, nullptr);
431 virtual void idle() {}
433 // -------------------------------------------------------------------
436 const NativeHostDescriptor
* const pHost
;
438 // -------------------------------------------------------------------
442 #define handlePtr ((NativePluginClass*)handle)
444 static uint32_t _get_parameter_count(NativePluginHandle handle
)
446 return handlePtr
->getParameterCount();
449 static const NativeParameter
* _get_parameter_info(NativePluginHandle handle
, uint32_t index
)
451 return handlePtr
->getParameterInfo(index
);
454 static float _get_parameter_value(NativePluginHandle handle
, uint32_t index
)
456 return handlePtr
->getParameterValue(index
);
459 static uint32_t _get_midi_program_count(NativePluginHandle handle
)
461 return handlePtr
->getMidiProgramCount();
464 static const NativeMidiProgram
* _get_midi_program_info(NativePluginHandle handle
, uint32_t index
)
466 return handlePtr
->getMidiProgramInfo(index
);
469 static void _set_parameter_value(NativePluginHandle handle
, uint32_t index
, float value
)
471 handlePtr
->setParameterValue(index
, value
);
474 static void _set_midi_program(NativePluginHandle handle
, uint8_t channel
, uint32_t bank
, uint32_t program
)
476 handlePtr
->setMidiProgram(channel
, bank
, program
);
479 static void _set_custom_data(NativePluginHandle handle
, const char* key
, const char* value
)
481 handlePtr
->setCustomData(key
, value
);
484 static void _ui_show(NativePluginHandle handle
, bool show
)
486 handlePtr
->uiShow(show
);
489 static void _ui_idle(NativePluginHandle handle
)
494 static void _ui_set_parameter_value(NativePluginHandle handle
, uint32_t index
, float value
)
496 handlePtr
->uiSetParameterValue(index
, value
);
499 static void _ui_set_midi_program(NativePluginHandle handle
, uint8_t channel
, uint32_t bank
, uint32_t program
)
501 handlePtr
->uiSetMidiProgram(channel
, bank
, program
);
504 static void _ui_set_custom_data(NativePluginHandle handle
, const char* key
, const char* value
)
506 handlePtr
->uiSetCustomData(key
, value
);
509 static void _activate(NativePluginHandle handle
)
511 handlePtr
->activate();
514 static void _deactivate(NativePluginHandle handle
)
516 handlePtr
->deactivate();
519 // FIXME for v3.0, use const for the input buffer
520 static void _process(NativePluginHandle handle
,
521 float** inBuffer
, float** outBuffer
, const uint32_t frames
,
522 const NativeMidiEvent
* midiEvents
, uint32_t midiEventCount
)
524 handlePtr
->process(inBuffer
, outBuffer
, frames
, midiEvents
, midiEventCount
);
527 static char* _get_state(NativePluginHandle handle
)
529 return handlePtr
->getState();
532 static void _set_state(NativePluginHandle handle
, const char* data
)
534 handlePtr
->setState(data
);
537 static intptr_t _dispatcher(NativePluginHandle handle
,
538 NativePluginDispatcherOpcode opcode
, int32_t index
, intptr_t value
, void* ptr
, float opt
)
542 case NATIVE_PLUGIN_OPCODE_NULL
:
544 case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED
:
545 CARLA_SAFE_ASSERT_RETURN(value
> 0, 0);
546 handlePtr
->bufferSizeChanged(static_cast<uint32_t>(value
));
548 case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED
:
549 CARLA_SAFE_ASSERT_RETURN(opt
> 0.0f
, 0);
550 handlePtr
->sampleRateChanged(static_cast<double>(opt
));
552 case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED
:
553 handlePtr
->offlineChanged(value
!= 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
));
559 case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE
:
561 case NATIVE_PLUGIN_OPCODE_IDLE
:
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 case NATIVE_PLUGIN_OPCODE_HOST_OPTION
:
580 static const NativeInlineDisplayImageSurface
* _render_inline_display(NativePluginHandle handle
, uint32_t width
, uint32_t height
)
582 return handlePtr
->renderInlineDisplay(width
, height
);
587 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginClass
)
593 // --------------------------------------------------------------------------------------------------------------------
594 // -Weffc++ compat ext widget
598 typedef struct _NativeInlineDisplayImageSurfaceCompat
{
600 int width
, height
, stride
;
603 _NativeInlineDisplayImageSurfaceCompat() noexcept
604 : data(nullptr), width(0), height(0), stride(0), dataSize(0) {}
606 } NativeInlineDisplayImageSurfaceCompat
;
610 // --------------------------------------------------------------------------------------------------------------------
612 #define PluginClassEND(ClassName) \
614 static NativePluginHandle _instantiate(const NativeHostDescriptor* host) \
616 return (host != nullptr) ? new ClassName(host) : nullptr; \
618 static void _cleanup(NativePluginHandle handle) \
620 delete (ClassName*)handle; \
623 #define PluginDescriptorFILL(ClassName) \
624 ClassName::_instantiate, \
625 ClassName::_cleanup, \
626 ClassName::_get_parameter_count, \
627 ClassName::_get_parameter_info, \
628 ClassName::_get_parameter_value, \
629 ClassName::_get_midi_program_count, \
630 ClassName::_get_midi_program_info, \
631 ClassName::_set_parameter_value, \
632 ClassName::_set_midi_program, \
633 ClassName::_set_custom_data, \
634 ClassName::_ui_show, \
635 ClassName::_ui_idle, \
636 ClassName::_ui_set_parameter_value, \
637 ClassName::_ui_set_midi_program, \
638 ClassName::_ui_set_custom_data, \
639 ClassName::_activate, \
640 ClassName::_deactivate, \
641 ClassName::_process, \
642 ClassName::_get_state, \
643 ClassName::_set_state, \
644 ClassName::_dispatcher, \
645 ClassName::_render_inline_display, \
646 0, 0, nullptr, nullptr, 0, 0
648 // --------------------------------------------------------------------------------------------------------------------
650 #endif // CARLA_NATIVE_HPP_INCLUDED