paulxstretch/deps/clap-juce-extensions/clap-libs/clap-helpers/include/clap/helpers/plugin.hh
essej 7fe70ed89b git subrepo clone (merge) https://github.com/free-audio/clap-helpers.git deps/clap-juce-extensions/clap-libs/clap-helpers
subrepo:
  subdir:   "deps/clap-juce-extensions/clap-libs/clap-helpers"
  merged:   "2bb43c187"
upstream:
  origin:   "https://github.com/free-audio/clap-helpers.git"
  branch:   "main"
  commit:   "2bb43c187"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo.git"
  commit:   "2f68596"
2022-06-14 21:35:21 -04:00

435 lines
19 KiB
C++

#pragma once
#include <cassert>
#include <functional>
#include <mutex>
#include <queue>
#include <string>
#include <string_view>
#include <vector>
#include <clap/clap.h>
#include "checking-level.hh"
#include "host-proxy.hh"
#include "misbehaviour-handler.hh"
namespace clap { namespace helpers {
/// @brief C++ glue and checks
///
/// @note for an higher level implementation, see @ref PluginHelper
template <MisbehaviourHandler h, CheckingLevel l>
class Plugin {
public:
const clap_plugin *clapPlugin() noexcept { return &_plugin; }
protected:
Plugin(const clap_plugin_descriptor *desc, const clap_host *host);
virtual ~Plugin() = default;
// not copyable, not moveable
Plugin(const Plugin &) = delete;
Plugin(Plugin &&) = delete;
Plugin &operator=(const Plugin &) = delete;
Plugin &operator=(Plugin &&) = delete;
/////////////////////////
// Methods to override //
/////////////////////////
//-------------//
// clap_plugin //
//-------------//
virtual bool init() noexcept { return true; }
virtual bool
activate(double sampleRate, uint32_t minFrameCount, uint32_t maxFrameCount) noexcept {
return true;
}
virtual void deactivate() noexcept {}
virtual bool startProcessing() noexcept { return true; }
virtual void stopProcessing() noexcept {}
virtual clap_process_status process(const clap_process *process) noexcept {
return CLAP_PROCESS_SLEEP;
}
virtual void reset() noexcept {}
virtual void onMainThread() noexcept {}
virtual const void *extension(const char *id) noexcept { return nullptr; }
//---------------------//
// clap_plugin_latency //
//---------------------//
virtual bool implementsLatency() const noexcept { return false; }
virtual uint32_t latencyGet() const noexcept { return 0; }
//------------------//
// clap_plugin_tail //
//------------------//
virtual bool implementsTail() const noexcept { return false; }
virtual uint32_t tailGet(const clap_plugin_t *plugin) const noexcept { return 0; }
//--------------------//
// clap_plugin_render //
//--------------------//
virtual bool implementsRender() const noexcept { return false; }
virtual bool renderHasHardRealtimeRequirement() noexcept { return false; }
virtual bool renderSetMode(clap_plugin_render_mode mode) noexcept { return false; }
//-------------------------//
// clap_plugin_thread_pool //
//-------------------------//
virtual bool implementsThreadPool() const noexcept { return false; }
virtual void threadPoolExec(uint32_t taskIndex) noexcept {}
//-------------------//
// clap_plugin_state //
//-------------------//
virtual bool implementsState() const noexcept { return false; }
virtual bool stateSave(const clap_ostream *stream) noexcept { return false; }
virtual bool stateLoad(const clap_istream *stream) noexcept { return false; }
//-------------------------//
// clap_plugin_preset_load //
//-------------------------//
virtual bool implementsPresetLoad() const noexcept { return false; }
virtual bool presetLoadFromFile(const char *path) noexcept { return false; }
//------------------------//
// clap_plugin_track_info //
//------------------------//
virtual bool implementsTrackInfo() const noexcept { return false; }
virtual void trackInfoChanged() noexcept {}
//-------------------------//
// clap_plugin_audio_ports //
//-------------------------//
virtual bool implementsAudioPorts() const noexcept { return false; }
virtual uint32_t audioPortsCount(bool isInput) const noexcept { return 0; }
virtual bool
audioPortsInfo(uint32_t index, bool isInput, clap_audio_port_info *info) const noexcept {
return false;
}
virtual uint32_t audioPortsConfigCount() const noexcept { return 0; }
virtual bool audioPortsGetConfig(uint32_t index,
clap_audio_ports_config *config) const noexcept {
return false;
}
virtual bool audioPortsSetConfig(clap_id configId) noexcept { return false; }
//--------------------//
// clap_plugin_params //
//--------------------//
virtual bool implementsParams() const noexcept { return false; }
virtual uint32_t paramsCount() const noexcept { return 0; }
virtual bool paramsInfo(uint32_t paramIndex, clap_param_info *info) const noexcept {
return false;
}
virtual bool paramsValue(clap_id paramId, double *value) noexcept { return false; }
virtual bool
paramsValueToText(clap_id paramId, double value, char *display, uint32_t size) noexcept {
return false;
}
virtual bool paramsTextToValue(clap_id paramId, const char *display, double *value) noexcept {
return false;
}
virtual void paramsFlush(const clap_input_events *in,
const clap_output_events *out) noexcept {}
virtual bool isValidParamId(clap_id paramId) const noexcept;
//----------------------------//
// clap_plugin_quick_controls //
//----------------------------//
virtual bool implementQuickControls() const noexcept { return false; }
virtual uint32_t quickControlsPageCount() noexcept { return 0; }
virtual bool quickControlsPageGet(uint32_t pageIndex,
clap_quick_controls_page *page) noexcept {
return false;
}
virtual void quickControlsSelectPage(clap_id pageId) noexcept {}
virtual clap_id quickControlsSelectedPage() noexcept { return CLAP_INVALID_ID; }
//------------------------//
// clap_plugin_note_ports //
//------------------------//
virtual bool implementsNotePorts() const noexcept { return false; }
virtual uint32_t notePortsCount(bool isInput) const noexcept { return 0; }
virtual bool
notePortsInfo(uint32_t index, bool isInput, clap_note_port_info *info) const noexcept {
return false;
}
//-----------------------//
// clap_plugin_note_name //
//-----------------------//
virtual bool implementsNoteName() const noexcept { return false; }
virtual int noteNameCount() noexcept { return 0; }
virtual bool noteNameGet(int index, clap_note_name *noteName) noexcept { return false; }
//---------------------------//
// clap_plugin_timer_support //
//---------------------------//
virtual bool implementsTimerSupport() const noexcept { return false; }
virtual void onTimer(clap_id timerId) noexcept {}
//------------------------------//
// clap_plugin_posix_fd_support //
//------------------------------//
virtual bool implementsPosixFdSupport() const noexcept { return false; }
virtual void onPosixFd(int fd, int flags) noexcept {}
//-----------------//
// clap_plugin_gui //
//-----------------//
virtual bool implementsGui() const noexcept { return false; }
virtual bool guiIsApiSupported(const char *api, bool isFloating) noexcept { return false; }
virtual bool guiGetPreferredApi(const char **api, bool *is_floating) noexcept {
return false;
}
virtual bool guiCreate(const char *api, bool isFloating) noexcept { return false; }
virtual void guiDestroy() noexcept {}
virtual bool guiSetScale(double scale) noexcept { return false; }
virtual bool guiShow() noexcept { return false; }
virtual bool guiHide() noexcept { return false; }
virtual bool guiGetSize(uint32_t *width, uint32_t *height) noexcept { return false; }
virtual bool guiCanResize() const noexcept { return false; }
virtual bool guiGetResizeHints(clap_gui_resize_hints_t *hints) noexcept { return false; }
virtual bool guiAdjustSize(uint32_t *width, uint32_t *height) noexcept {
return guiGetSize(width, height);
}
virtual bool guiSetSize(uint32_t width, uint32_t height) noexcept { return false; }
virtual void guiSuggestTitle(const char *title) noexcept {}
virtual bool guiSetParent(const clap_window *window) noexcept { return false; }
virtual bool guiSetTransient(const clap_window *window) noexcept { return false; }
//------------------------//
// clap_plugin_voice_info //
//------------------------//
virtual bool implementsVoiceInfo() const noexcept { return false; }
virtual bool voiceInfoGet(clap_voice_info *info) noexcept { return false; }
/////////////
// Logging //
/////////////
void log(clap_log_severity severity, const char *msg) const noexcept;
void hostMisbehaving(const char *msg) const noexcept;
void hostMisbehaving(const std::string &msg) const noexcept { hostMisbehaving(msg.c_str()); }
// Receives a copy of all the logging messages sent to the host.
// This is useful to have the messages in both the host's logs and the plugin's logs.
virtual void logTee(clap_log_severity severity, const char *msg) const noexcept {}
/////////////////////
// Thread Checking //
/////////////////////
void checkMainThread() const noexcept;
void checkAudioThread() const noexcept;
void checkParamThread() const noexcept;
void ensureMainThread(const char *method) const noexcept;
void ensureAudioThread(const char *method) const noexcept;
void ensureParamThread(const char *method) const noexcept;
///////////////
// Utilities //
///////////////
static Plugin &from(const clap_plugin *plugin, bool requireInitialized = true) noexcept;
// runs the callback immediately if on the main thread, otherwise queue it.
// be aware that the callback may be ran during the plugin destruction phase,
// so check isBeingDestroyed() and ajust your code.
void runOnMainThread(std::function<void()> callback);
// This actually runs callbacks on the main thread, you should not need to call it
void runCallbacksOnMainThread();
template <typename T>
void initInterface(const T *&ptr, const char *id) noexcept;
void initInterfaces() noexcept;
static uint32_t compareAudioPortsInfo(const clap_audio_port_info &a,
const clap_audio_port_info &b) noexcept;
//////////////////////
// Processing State //
//////////////////////
bool isActive() const noexcept { return _isActive; }
bool isProcessing() const noexcept { return _isProcessing; }
int sampleRate() const noexcept {
assert(_isActive && "sample rate is only known if the plugin is active");
assert(_sampleRate > 0);
return _sampleRate;
}
bool isBeingDestroyed() const noexcept { return _isBeingDestroyed; }
protected:
HostProxy<h, l> _host;
private:
/////////////////////
// CLAP Interfaces //
/////////////////////
clap_plugin _plugin;
// clap_plugin
static bool clapInit(const clap_plugin *plugin) noexcept;
static void clapDestroy(const clap_plugin *plugin) noexcept;
static bool clapActivate(const clap_plugin *plugin,
double sample_rate,
uint32_t minFrameCount,
uint32_t maxFrameCount) noexcept;
static void clapDeactivate(const clap_plugin *plugin) noexcept;
static bool clapStartProcessing(const clap_plugin *plugin) noexcept;
static void clapStopProcessing(const clap_plugin *plugin) noexcept;
static void clapReset(const clap_plugin *plugin) noexcept;
static clap_process_status clapProcess(const clap_plugin *plugin,
const clap_process *process) noexcept;
static void clapOnMainThread(const clap_plugin *plugin) noexcept;
static const void *clapExtension(const clap_plugin *plugin, const char *id) noexcept;
// latency
static uint32_t clapLatencyGet(const clap_plugin *plugin) noexcept;
// clap_plugin_tail
static uint32_t clapTailGet(const clap_plugin_t *plugin) noexcept;
// clap_plugin_render
static bool clapRenderHasHardRealtimeRequirement(const clap_plugin_t *plugin) noexcept;
static bool clapRenderSetMode(const clap_plugin *plugin,
clap_plugin_render_mode mode) noexcept;
// clap_plugin_thread_pool
static void clapThreadPoolExec(const clap_plugin *plugin, uint32_t task_index) noexcept;
// clap_plugin_state
static bool clapStateSave(const clap_plugin *plugin, const clap_ostream *stream) noexcept;
static bool clapStateLoad(const clap_plugin *plugin, const clap_istream *stream) noexcept;
// clap_plugin_preset
static bool clapPresetLoadFromFile(const clap_plugin *plugin, const char *path) noexcept;
// clap_plugin_track_info
static void clapTrackInfoChanged(const clap_plugin *plugin) noexcept;
// clap_plugin_audio_ports
static uint32_t clapAudioPortsCount(const clap_plugin *plugin, bool is_input) noexcept;
static bool clapAudioPortsInfo(const clap_plugin *plugin,
uint32_t index,
bool is_input,
clap_audio_port_info *info) noexcept;
static uint32_t clapAudioPortsConfigCount(const clap_plugin *plugin) noexcept;
static bool clapAudioPortsGetConfig(const clap_plugin *plugin,
uint32_t index,
clap_audio_ports_config *config) noexcept;
static bool clapAudioPortsSetConfig(const clap_plugin *plugin, clap_id config_id) noexcept;
// clap_plugin_params
static uint32_t clapParamsCount(const clap_plugin *plugin) noexcept;
static bool clapParamsInfo(const clap_plugin *plugin,
uint32_t param_index,
clap_param_info *param_info) noexcept;
static bool
clapParamsValue(const clap_plugin *plugin, clap_id param_id, double *value) noexcept;
static bool clapParamsValueToText(const clap_plugin *plugin,
clap_id param_id,
double value,
char *display,
uint32_t size) noexcept;
static bool clapParamsTextToValue(const clap_plugin *plugin,
clap_id param_id,
const char *display,
double *value) noexcept;
static void clapParamsFlush(const clap_plugin *plugin,
const clap_input_events *in,
const clap_output_events *out) noexcept;
// clap_plugin_quick_controls
static uint32_t clapQuickControlsPageCount(const clap_plugin *plugin) noexcept;
static bool clapQuickControlsPageGet(const clap_plugin *plugin,
uint32_t page_index,
clap_quick_controls_page *page) noexcept;
// clap_plugin_note_port
static uint32_t clapNotePortsCount(const clap_plugin *plugin, bool is_input) noexcept;
static bool clapNotePortsInfo(const clap_plugin *plugin,
uint32_t index,
bool is_input,
clap_note_port_info *info) noexcept;
// clap_plugin_note_name
static uint32_t clapNoteNameCount(const clap_plugin *plugin) noexcept;
static bool clapNoteNameGet(const clap_plugin *plugin,
uint32_t index,
clap_note_name *note_name) noexcept;
// clap_plugin_timer_support
static void clapOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept;
// clap_plugin_fd_support
static void
clapOnPosixFd(const clap_plugin *plugin, int fd, clap_posix_fd_flags_t flags) noexcept;
// clap_plugin_gui
static bool
clapGuiIsApiSupported(const clap_plugin *plugin, const char *api, bool isFloating) noexcept;
static bool clapGuiGetPreferredApi(const clap_plugin_t *plugin,
const char **api,
bool *is_floating) noexcept;
static bool
clapGuiCreate(const clap_plugin *plugin, const char *api, bool isFloating) noexcept;
static void clapGuiDestroy(const clap_plugin *plugin) noexcept;
static bool clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept;
static bool
clapGuiGetSize(const clap_plugin *plugin, uint32_t *width, uint32_t *height) noexcept;
static bool
clapGuiSetSize(const clap_plugin *plugin, uint32_t width, uint32_t height) noexcept;
static bool clapGuiCanResize(const clap_plugin *plugin) noexcept;
static bool clapGuiGetResizeHints(const clap_plugin_t *plugin,
clap_gui_resize_hints_t *hints) noexcept;
static bool
clapGuiAdjustSize(const clap_plugin *plugin, uint32_t *width, uint32_t *height) noexcept;
static bool clapGuiShow(const clap_plugin *plugin) noexcept;
static bool clapGuiHide(const clap_plugin *plugin) noexcept;
static bool clapGuiSetParent(const clap_plugin *plugin, const clap_window *window) noexcept;
static bool clapGuiSetTransient(const clap_plugin *plugin,
const clap_window *window) noexcept;
static void clapGuiSuggestTitle(const clap_plugin *plugin, const char *title) noexcept;
static bool clapVoiceInfoGet(const clap_plugin *plugin, clap_voice_info *info) noexcept;
// interfaces
static const clap_plugin_render _pluginRender;
static const clap_plugin_thread_pool _pluginThreadPool;
static const clap_plugin_state _pluginState;
static const clap_plugin_preset_load _pluginPresetLoad;
static const clap_plugin_track_info _pluginTrackInfo;
static const clap_plugin_audio_ports _pluginAudioPorts;
static const clap_plugin_audio_ports_config _pluginAudioPortsConfig;
static const clap_plugin_params _pluginParams;
static const clap_plugin_quick_controls _pluginQuickControls;
static const clap_plugin_latency _pluginLatency;
static const clap_plugin_note_ports _pluginNotePorts;
static const clap_plugin_note_name _pluginNoteName;
static const clap_plugin_timer_support _pluginTimerSupport;
static const clap_plugin_posix_fd_support _pluginPosixFdSupport;
static const clap_plugin_gui _pluginGui;
static const clap_plugin_voice_info _pluginVoiceInfo;
static const clap_plugin_tail _pluginTail;
// state
bool _wasInitialized = false;
bool _isActive = false;
bool _isProcessing = false;
bool _isBeingDestroyed = false;
double _sampleRate = 0;
std::string _guiApi;
bool _isGuiCreated = false;
bool _isGuiFloating = false;
bool _isGuiEmbedded = false;
std::mutex _mainThredCallbacksLock;
std::queue<std::function<void()>> _mainThredCallbacks;
};
}} // namespace clap::helpers