commit 81bb370b4be5384f47fe308cb68155af9adf7005
parent 74c01b879b7f14b83d8c097bc524734d86ca01d6
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date: Mon, 7 Jun 2021 23:10:39 +0200
Create a glue library to make the Plugin class re-usable
Diffstat:
9 files changed, 1219 insertions(+), 1212 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(CLAP C CXX)
+set(ENABLE_CLAP_GLUE TRUE CACHE BOOL "Enables the helper glue code")
set(ENABLE_CLAP_HOST FALSE CACHE BOOL "Enables the example host")
set(ENABLE_CLAP_PLUGINS FALSE CACHE BOOL "Enables the example plugins")
set(ENABLE_CLAP_GUI FALSE CACHE BOOL "Enables the plugin GUI framework")
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
@@ -1,12 +1,16 @@
-if (ENABLE_CLAP_HOST)
- add_subdirectory(host)
+if(ENABLE_CLAP_GLUE)
+ add_subdirectory(glue)
endif()
-if (ENABLE_CLAP_GUI OR ENABLE_CLAP_PLUGINS)
- add_subdirectory(gui)
- add_subdirectory(gui-proxy)
+if(ENABLE_CLAP_HOST)
+ add_subdirectory(host)
endif()
-if (ENABLE_CLAP_PLUGINS)
- add_subdirectory(plugins)
-endif()
-\ No newline at end of file
+if(ENABLE_CLAP_GUI OR ENABLE_CLAP_PLUGINS)
+ add_subdirectory(gui)
+ add_subdirectory(gui-proxy)
+endif()
+
+if(ENABLE_CLAP_PLUGINS)
+ add_subdirectory(plugins)
+endif()
diff --git a/examples/glue/CMakeLists.txt b/examples/glue/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_library(clap-plugin-glue EXCLUDE_FROM_ALL STATIC clap-plugin.cc
+ clap-plugin.hh)
+set_target_properties(clap-plugin-glue PROPERTIES CXX_STANDARD 17
+ POSITION_INDEPENDENT_CODE ON)
+target_include_directories(clap-plugin-glue INTERFACE .)
diff --git a/examples/glue/clap-plugin.cc b/examples/glue/clap-plugin.cc
@@ -0,0 +1,753 @@
+#include <cassert>
+#include <cstring>
+#include <filesystem>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <utility>
+
+#include "clap-plugin.hh"
+
+namespace clap {
+
+ Plugin::Plugin(const clap_plugin_descriptor *desc, const clap_host *host) : host_(host) {
+ plugin_.plugin_data = this;
+ plugin_.desc = desc;
+ plugin_.init = Plugin::clapInit;
+ plugin_.destroy = Plugin::clapDestroy;
+ plugin_.extension = nullptr;
+ plugin_.process = nullptr;
+ plugin_.activate = nullptr;
+ plugin_.deactivate = nullptr;
+ plugin_.start_processing = nullptr;
+ plugin_.stop_processing = nullptr;
+ }
+
+ /////////////////////
+ // CLAP Interfaces //
+ /////////////////////
+
+ //-------------//
+ // clap_plugin //
+ //-------------//
+ bool Plugin::clapInit(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+
+ self.plugin_.extension = Plugin::clapExtension;
+ self.plugin_.process = Plugin::clapProcess;
+ self.plugin_.activate = Plugin::clapActivate;
+ self.plugin_.deactivate = Plugin::clapDeactivate;
+ self.plugin_.start_processing = Plugin::clapStartProcessing;
+ self.plugin_.stop_processing = Plugin::clapStopProcessing;
+
+ self.initInterfaces();
+ self.ensureMainThread("clap_plugin.init");
+ return self.init();
+ }
+
+ void Plugin::clapDestroy(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin.destroy");
+ delete &from(plugin);
+ }
+
+ bool Plugin::clapActivate(const clap_plugin *plugin, int sample_rate) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin.activate");
+
+ if (self.isActive_) {
+ self.hostMisbehaving("Plugin was activated twice");
+
+ if (sample_rate != self.sampleRate_) {
+ std::ostringstream msg;
+ msg << "The plugin was activated twice and with different sample rates: "
+ << self.sampleRate_ << " and " << sample_rate
+ << ". The host must deactivate the plugin first." << std::endl
+ << "Simulating deactivation.";
+ self.hostMisbehaving(msg.str());
+ clapDeactivate(plugin);
+ }
+ }
+
+ if (sample_rate <= 0) {
+ std::ostringstream msg;
+ msg << "The plugin was activated with an invalid sample rates: " << sample_rate;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ assert(!self.isActive_);
+ assert(self.sampleRate_ == 0);
+
+ if (!self.activate(sample_rate)) {
+ assert(!self.isActive_);
+ assert(self.sampleRate_ == 0);
+ return false;
+ }
+
+ self.isActive_ = true;
+ self.sampleRate_ = sample_rate;
+ return true;
+ }
+
+ void Plugin::clapDeactivate(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin.deactivate");
+
+ if (!self.isActive_) {
+ self.hostMisbehaving("The plugin was deactivated twice.");
+ return;
+ }
+
+ self.deactivate();
+ }
+
+ bool Plugin::clapStartProcessing(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureAudioThread("clap_plugin.start_processing");
+
+ if (!self.isActive_) {
+ self.hostMisbehaving("Host called clap_plugin.start_processing() on a deactivated plugin");
+ return false;
+ }
+
+ if (self.isProcessing_) {
+ self.hostMisbehaving("Host called clap_plugin.start_processing() twice");
+ return true;
+ }
+
+ self.isProcessing_ = self.startProcessing();
+ return self.isProcessing_;
+ }
+
+ void Plugin::clapStopProcessing(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureAudioThread("clap_plugin.stop_processing");
+
+ if (!self.isActive_) {
+ self.hostMisbehaving("Host called clap_plugin.stop_processing() on a deactivated plugin");
+ return;
+ }
+
+ if (!self.isProcessing_) {
+ self.hostMisbehaving("Host called clap_plugin.stop_processing() twice");
+ return;
+ }
+
+ self.stopProcessing();
+ self.isProcessing_ = false;
+ }
+
+ clap_process_status Plugin::clapProcess(const clap_plugin *plugin,
+ const clap_process *process) noexcept {
+ auto &self = from(plugin);
+ self.ensureAudioThread("clap_plugin.process");
+
+ if (!self.isActive_) {
+ self.hostMisbehaving("Host called clap_plugin.process() on a deactivated plugin");
+ return CLAP_PROCESS_ERROR;
+ }
+
+ if (!self.isProcessing_) {
+ self.hostMisbehaving(
+ "Host called clap_plugin.process() without calling clap_plugin.start_processing()");
+ return CLAP_PROCESS_ERROR;
+ }
+
+ return self.process(process);
+ }
+
+ const void *Plugin::clapExtension(const clap_plugin *plugin, const char *id) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin.extension");
+
+ if (!strcmp(id, CLAP_EXT_STATE) && self.implementsState())
+ return &pluginState_;
+ if (!strcmp(id, CLAP_EXT_PRESET_LOAD) && self.implementsPresetLoad())
+ return &pluginPresetLoad_;
+ if (!strcmp(id, CLAP_EXT_RENDER) && self.implementsRender())
+ return &pluginRender_;
+ if (!strcmp(id, CLAP_EXT_TRACK_INFO) && self.implementsTrackInfo())
+ return &pluginTrackInfo_;
+ if (!strcmp(id, CLAP_EXT_LATENCY) && self.implementsLatency())
+ return &pluginLatency_;
+ if (!strcmp(id, CLAP_EXT_AUDIO_PORTS) && self.implementsAudioPorts())
+ return &pluginAudioPorts_;
+ if (!strcmp(id, CLAP_EXT_PARAMS) && self.implementsParams())
+ return &pluginParams_;
+ if (!strcmp(id, CLAP_EXT_NOTE_NAME) && self.implementsNoteName())
+ return &pluginNoteName_;
+ if (!strcmp(id, CLAP_EXT_THREAD_POOL) && self.implementsThreadPool())
+ return &pluginThreadPool_;
+ if (!strcmp(id, CLAP_EXT_EVENT_LOOP) && self.implementsEventLoop())
+ return &pluginEventLoop_;
+ if (!strcmp(id, CLAP_EXT_GUI) && self.implementsGui())
+ return &pluginGui_;
+ if (!strcmp(id, CLAP_EXT_GUI_X11) && self.implementsGuiX11())
+ return &pluginGuiX11_;
+ if (!strcmp(id, CLAP_EXT_GUI_WIN32) && self.implementsGuiWin32())
+ return &pluginGuiWin32_;
+ if (!strcmp(id, CLAP_EXT_GUI_COCOA) && self.implementsGuiCocoa())
+ return &pluginGuiCocoa_;
+ if (!strcmp(id, CLAP_EXT_GUI_FREE_STANDING) && self.implementsGuiFreeStanding())
+ return &pluginGuiFreeStanding_;
+
+ return from(plugin).extension(id);
+ }
+
+ template <typename T>
+ void Plugin::initInterface(const T *&ptr, const char *id) noexcept {
+ assert(!ptr);
+ assert(id);
+
+ if (host_->extension)
+ ptr = static_cast<const T *>(host_->extension(host_, id));
+ }
+
+ void Plugin::initInterfaces() noexcept {
+ initInterface(hostLog_, CLAP_EXT_LOG);
+ initInterface(hostThreadCheck_, CLAP_EXT_THREAD_CHECK);
+ initInterface(hostThreadPool_, CLAP_EXT_THREAD_POOL);
+ initInterface(hostAudioPorts_, CLAP_EXT_AUDIO_PORTS);
+ initInterface(hostEventLoop_, CLAP_EXT_EVENT_LOOP);
+ initInterface(hostEventFilter_, CLAP_EXT_EVENT_FILTER);
+ initInterface(hostFileReference_, CLAP_EXT_FILE_REFERENCE);
+ initInterface(hostLatency_, CLAP_EXT_LATENCY);
+ initInterface(hostGui_, CLAP_EXT_GUI);
+ initInterface(hostParams_, CLAP_EXT_PARAMS);
+ initInterface(hostTrackInfo_, CLAP_EXT_TRACK_INFO);
+ initInterface(hostState_, CLAP_EXT_STATE);
+ initInterface(hostNoteName_, CLAP_EXT_NOTE_NAME);
+ }
+
+ //-------------------//
+ // clap_plugin_state //
+ //-------------------//
+ uint32_t Plugin::clapLatencyGet(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_latency.get");
+
+ return self.latencyGet();
+ }
+
+ //--------------------//
+ // clap_plugin_render //
+ //--------------------//
+ void Plugin::clapRenderSetMode(const clap_plugin *plugin,
+ clap_plugin_render_mode mode) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_render.set_mode");
+
+ switch (mode) {
+ case CLAP_RENDER_REALTIME:
+ case CLAP_RENDER_OFFLINE:
+ self.renderSetMode(mode);
+ break;
+
+ default: {
+ std::ostringstream msg;
+ msg << "host called clap_plugin_render.set_mode with an unknown mode : " << mode;
+ self.hostMisbehaving(msg.str());
+ break;
+ }
+ }
+ }
+
+ //-------------------------//
+ // clap_plugin_thread_pool //
+ //-------------------------//
+ void Plugin::clapThreadPoolExec(const clap_plugin *plugin, uint32_t task_index) noexcept {
+ auto &self = from(plugin);
+
+ self.threadPoolExec(task_index);
+ }
+
+ //-------------------//
+ // clap_plugin_state //
+ //-------------------//
+ bool Plugin::clapStateSave(const clap_plugin *plugin, clap_ostream *stream) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_state.save");
+
+ return self.stateSave(stream);
+ }
+
+ bool Plugin::clapStateLoad(const clap_plugin *plugin, clap_istream *stream) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_state.load");
+
+ return self.stateLoad(stream);
+ }
+
+ bool Plugin::clapStateIsDirty(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_state.is_dirty");
+
+ return self.stateIsDirty();
+ }
+
+ //-------------------------//
+ // clap_plugin_preset_load //
+ //-------------------------//
+ bool Plugin::clapPresetLoadFromFile(const clap_plugin *plugin, const char *path) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_preset_load.from_file");
+
+ if (!path) {
+ self.hostMisbehaving("host called clap_plugin_preset_load.from_file with a null path");
+ return false;
+ }
+
+ // TODO check if the file is readable
+
+ return self.presetLoadFromFile(path);
+ }
+
+ //------------------------//
+ // clap_plugin_track_info //
+ //------------------------//
+
+ void Plugin::clapTrackInfoChanged(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_track_info.changed");
+
+ if (!self.canUseTrackInfo()) {
+ self.hostMisbehaving("host called clap_plugin_track_info.changed() but does not provide a "
+ "complete clap_host_track_info interface");
+ return;
+ }
+
+ self.trackInfoChanged();
+ }
+
+ //-------------------------//
+ // clap_plugin_audio_ports //
+ //-------------------------//
+
+ uint32_t Plugin::clapAudioPortsCount(const clap_plugin *plugin, bool is_input) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_audio_ports.count");
+
+ return self.audioPortsCount(is_input);
+ }
+
+ bool Plugin::clapAudioPortsInfo(const clap_plugin *plugin,
+ uint32_t index,
+ bool is_input,
+ clap_audio_port_info *info) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_audio_ports.info");
+ auto count = clapAudioPortsCount(plugin, is_input);
+ if (index >= count) {
+ std::ostringstream msg;
+ msg << "Host called clap_plugin_audio_ports.info() with an index out of bounds: " << index
+ << " >= " << count;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ return self.audioPortsInfo(index, is_input, info);
+ }
+
+ uint32_t Plugin::clapAudioPortsConfigCount(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_audio_ports.config_count");
+ return self.audioPortsConfigCount();
+ }
+
+ bool Plugin::clapAudioPortsGetConfig(const clap_plugin *plugin,
+ uint32_t index,
+ clap_audio_ports_config *config) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_audio_ports.get_config");
+
+ auto count = clapAudioPortsConfigCount(plugin);
+ if (index >= count) {
+ std::ostringstream msg;
+ msg << "called clap_plugin_audio_ports.get_config with an index out of bounds: " << index
+ << " >= " << count;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+ return self.audioPortsGetConfig(index, config);
+ }
+
+ bool Plugin::clapAudioPortsSetConfig(const clap_plugin *plugin, clap_id config_id) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_audio_ports.get_config");
+
+ if (self.isActive())
+ self.hostMisbehaving(
+ "it is illegal to call clap_audio_ports.set_config if the plugin is active");
+
+ return self.audioPortsSetConfig(config_id);
+ }
+
+ uint32_t Plugin::clapParamsCount(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.count");
+
+ return self.paramsCount();
+ }
+
+ //--------------------//
+ // clap_plugin_params //
+ //--------------------//
+ bool Plugin::clapParamsIinfo(const clap_plugin *plugin,
+ int32_t param_index,
+ clap_param_info *param_info) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.info");
+
+ auto count = clapParamsCount(plugin);
+ if (param_index >= count) {
+ std::ostringstream msg;
+ msg << "called clap_plugin_params.info with an index out of bounds: " << param_index
+ << " >= " << count;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ return self.paramsInfo(param_index, param_info);
+ }
+
+ bool Plugin::clapParamsEnumValue(const clap_plugin *plugin,
+ clap_id param_id,
+ int32_t value_index,
+ clap_param_value *value) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.enum_value");
+
+ if (!self.isValidParamId(param_id)) {
+ std::ostringstream msg;
+ msg << "clap_plugin_params.enum_value called with invalid param_id: " << param_id;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ // TODO: check the value index?
+
+ return self.paramsEnumValue(param_id, value_index, value);
+ }
+
+ bool Plugin::clapParamsValue(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value *value) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.value");
+
+ if (!self.isValidParamId(param_id)) {
+ std::ostringstream msg;
+ msg << "clap_plugin_params.value called with invalid param_id: " << param_id;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ // TODO extra checks
+
+ return self.paramsValue(param_id, value);
+ }
+
+ bool Plugin::clapParamsSetValue(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value value,
+ clap_param_value modulation) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.set_value");
+
+ if (self.isActive_) {
+ self.hostMisbehaving(
+ "it is forbidden to call clap_plugin_params.set_value() if the plugin is activated");
+ return false;
+ }
+
+ if (!self.isValidParamId(param_id)) {
+ std::ostringstream msg;
+ msg << "clap_plugin_params.set_value called with invalid param_id: " << param_id;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ // TODO: extra checks
+
+ return self.paramsSetValue(param_id, value, modulation);
+ }
+
+ bool Plugin::clapParamsValueToText(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value value,
+ char *display,
+ uint32_t size) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.value_to_text");
+
+ if (!self.isValidParamId(param_id)) {
+ std::ostringstream msg;
+ msg << "clap_plugin_params.value_to_text called with invalid param_id: " << param_id;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ // TODO: extra checks
+ return self.paramsValueToText(param_id, value, display, size);
+ }
+
+ bool Plugin::clapParamsTextToValue(const clap_plugin *plugin,
+ clap_id param_id,
+ const char *display,
+ clap_param_value *value) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_params.text_to_value");
+
+ if (!self.isValidParamId(param_id)) {
+ std::ostringstream msg;
+ msg << "clap_plugin_params.text_to_value called with invalid param_id: " << param_id;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ // TODO: extra checks
+ return self.paramsTextToValue(param_id, display, value);
+ }
+
+ bool Plugin::isValidParamId(clap_id param_id) const noexcept {
+ checkMainThread();
+
+ auto count = paramsCount();
+ clap_param_info info;
+ for (uint32_t i = 0; i < count; ++i) {
+ if (!paramsInfo(i, &info))
+ // TODO: fatal error?
+ continue;
+
+ if (info.id == param_id)
+ return true;
+ }
+ return false;
+ }
+
+ //-----------------------//
+ // clap_plugin_note_name //
+ //-----------------------//
+
+ uint32_t Plugin::clapNoteNameCount(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_note_name.count");
+ return self.noteNameCount();
+ }
+
+ bool Plugin::clapNoteNameGet(const clap_plugin *plugin,
+ uint32_t index,
+ clap_note_name *note_name) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_note_name.get");
+
+ // TODO check index
+ auto count = clapNoteNameCount(plugin);
+ if (index >= count) {
+ std::ostringstream msg;
+ msg << "host called clap_plugin_note_name.get with an index out of bounds: " << index
+ << " >= " << count;
+ self.hostMisbehaving(msg.str());
+ return false;
+ }
+
+ return self.noteNameGet(index, note_name);
+ }
+
+ //------------------------//
+ // clap_plugin_event_loop //
+ //------------------------//
+ void Plugin::clapEventLoopOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_event_loop.on_timer");
+
+ if (timer_id == CLAP_INVALID_ID) {
+ self.hostMisbehaving(
+ "Host called clap_plugin_event_loop.on_timer with an invalid timer_id");
+ return;
+ }
+
+ self.eventLoopOnTimer(timer_id);
+ }
+
+ void Plugin::clapEventLoopOnFd(const clap_plugin *plugin, clap_fd fd, uint32_t flags) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_event_loop.on_fd");
+
+ self.eventLoopOnFd(fd, flags);
+ }
+
+ //-----------------//
+ // clap_plugin_gui //
+ //-----------------//
+ void Plugin::clapGuiSize(const clap_plugin *plugin, int32_t *width, int32_t *height) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui.size");
+
+ self.guiSize(width, height);
+ }
+
+ void Plugin::clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui.set_scale");
+
+ self.guiSetScale(scale);
+ }
+
+ void Plugin::clapGuiShow(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui.show");
+
+ self.guiShow();
+ }
+
+ void Plugin::clapGuiHide(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui.hide");
+
+ self.guiHide();
+ }
+
+ void Plugin::clapGuiClose(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui.close");
+
+ self.guiClose();
+ }
+
+ //---------------------//
+ // clap_plugin_gui_x11 //
+ //---------------------//
+ bool Plugin::clapGuiX11Attach(const clap_plugin *plugin,
+ const char *display_name,
+ unsigned long window) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui_x11.attach");
+
+ return self.guiX11Attach(display_name, window);
+ }
+
+ //-----------------------//
+ // clap_plugin_gui_win32 //
+ //-----------------------//
+ bool Plugin::clapGuiWin32Attach(const clap_plugin *plugin, clap_hwnd window) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui_win32.attach");
+
+ return self.guiWin32Attach(window);
+ }
+
+ //-----------------------//
+ // clap_plugin_gui_cocoa //
+ //-----------------------//
+ bool Plugin::clapGuiCocoaAttach(const clap_plugin *plugin, void *nsView) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui_cocoa.attach");
+
+ return self.guiCocoaAttach(nsView);
+ }
+
+ //-------------------------------//
+ // clap_plugin_gui_free_standing //
+ //-------------------------------//
+ bool Plugin::clapGuiFreeStandingOpen(const clap_plugin *plugin) noexcept {
+ auto &self = from(plugin);
+ self.ensureMainThread("clap_plugin_gui_win32.attach");
+
+ return self.guiFreeStandingOpen();
+ }
+
+ /////////////
+ // Logging //
+ /////////////
+ void Plugin::log(clap_log_severity severity, const char *msg) const noexcept {
+ if (canUseHostLog())
+ hostLog_->log(host_, severity, msg);
+ else
+ std::clog << msg << std::endl;
+ }
+
+ void Plugin::hostMisbehaving(const char *msg) const noexcept {
+ log(CLAP_LOG_HOST_MISBEHAVING, msg);
+ }
+
+ /////////////////////////////////
+ // Interface consistency check //
+ /////////////////////////////////
+
+ bool Plugin::canUseHostLog() const noexcept { return hostLog_ && hostLog_->log; }
+
+ bool Plugin::canUseThreadCheck() const noexcept {
+ return hostThreadCheck_ && hostThreadCheck_->is_audio_thread &&
+ hostThreadCheck_->is_main_thread;
+ }
+
+ /////////////////////
+ // Thread Checking //
+ /////////////////////
+
+ void Plugin::checkMainThread() const noexcept {
+ if (!hostThreadCheck_ || !hostThreadCheck_->is_main_thread ||
+ hostThreadCheck_->is_main_thread(host_))
+ return;
+
+ std::terminate();
+ }
+
+ void Plugin::ensureMainThread(const char *method) const noexcept {
+ if (!hostThreadCheck_ || !hostThreadCheck_->is_main_thread ||
+ hostThreadCheck_->is_main_thread(host_))
+ return;
+
+ std::ostringstream msg;
+ msg << "Host called the method " << method
+ << "() on wrong thread! It must be called on main thread!";
+ hostMisbehaving(msg.str());
+ std::terminate();
+ }
+
+ void Plugin::ensureAudioThread(const char *method) const noexcept {
+ if (!hostThreadCheck_ || !hostThreadCheck_->is_audio_thread ||
+ hostThreadCheck_->is_audio_thread(host_))
+ return;
+
+ std::ostringstream msg;
+ msg << "Host called the method " << method
+ << "() on wrong thread! It must be called on audio thread!";
+ hostMisbehaving(msg.str());
+ std::terminate();
+ }
+
+ ///////////////
+ // Utilities //
+ ///////////////
+ Plugin &Plugin::from(const clap_plugin *plugin) noexcept {
+ if (!plugin) {
+ std::cerr << "called with a null clap_plugin pointer!" << std::endl;
+ std::terminate();
+ }
+
+ if (!plugin->plugin_data) {
+ std::cerr << "called with a null clap_plugin->plugin_data pointer! The host must never "
+ "change this pointer!"
+ << std::endl;
+ std::terminate();
+ }
+
+ return *static_cast<Plugin *>(plugin->plugin_data);
+ }
+
+ uint32_t Plugin::compareAudioPortsInfo(const clap_audio_port_info &a,
+ const clap_audio_port_info &b) noexcept {
+ if (a.sample_size != b.sample_size || a.in_place != b.in_place || a.is_cv != b.is_cv ||
+ a.is_main != b.is_main || a.channel_count != b.channel_count ||
+ a.channel_map != b.channel_map || a.id != b.id)
+ return CLAP_AUDIO_PORTS_RESCAN_ALL;
+
+ if (strncmp(a.name, b.name, sizeof(a.name)))
+ return CLAP_AUDIO_PORTS_RESCAN_NAMES;
+
+ return 0;
+ }
+} // namespace clap
+\ No newline at end of file
diff --git a/examples/glue/clap-plugin.hh b/examples/glue/clap-plugin.hh
@@ -0,0 +1,440 @@
+#pragma once
+
+#include <cassert>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <clap/all.h>
+
+namespace clap {
+ /// @brief C++ glue and checks
+ ///
+ /// @note for an higher level implementation, see @ref PluginHelper
+ 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(int sampleRate) 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 const void *extension(const char *id) noexcept { return nullptr; }
+
+ //---------------------//
+ // clap_plugin_latenxy //
+ //---------------------//
+ virtual bool implementsLatency() const noexcept { return false; }
+ virtual uint32_t latencyGet() const noexcept { return 0; }
+
+ //--------------------//
+ // clap_plugin_render //
+ //--------------------//
+ virtual bool implementsRender() const noexcept { return false; }
+ virtual void renderSetMode(clap_plugin_render_mode mode) noexcept {}
+
+ //-------------------------//
+ // clap_plugin_thread_pool //
+ //-------------------------//
+ virtual bool implementsThreadPool() const noexcept { return false; }
+ virtual void threadPoolExec(uint32_t task_index) noexcept;
+
+ //-------------------//
+ // clap_plugin_state //
+ //-------------------//
+ virtual bool implementsState() const noexcept { return false; }
+ virtual bool stateSave(clap_ostream *stream) noexcept { return false; }
+ virtual bool stateLoad(clap_istream *stream) noexcept { return false; }
+ virtual bool stateIsDirty() const noexcept { return false; }
+ void stateMarkDirty() const noexcept {
+ if (canUseState())
+ hostState_->mark_dirty(host_);
+ }
+
+ //-------------------------//
+ // 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 is_input) const noexcept { return 0; }
+ virtual bool
+ audioPortsInfo(uint32_t index, bool is_input, 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 config_id) noexcept { return false; }
+
+ //--------------------//
+ // clap_plugin_params //
+ //--------------------//
+ virtual bool implementsParams() const noexcept { return false; }
+ virtual uint32_t paramsCount() const noexcept { return 0; }
+ virtual bool paramsInfo(int32_t paramIndex, clap_param_info *info) const noexcept {
+ return false;
+ }
+ virtual bool
+ paramsEnumValue(clap_id paramId, int32_t valueIndex, clap_param_value *value) noexcept {
+ return false;
+ }
+ virtual bool paramsValue(clap_id paramId, clap_param_value *value) noexcept { return false; }
+ virtual bool paramsSetValue(clap_id paramId,
+ clap_param_value value,
+ clap_param_value modulation) noexcept {
+ return false;
+ }
+ virtual bool paramsValueToText(clap_id paramId,
+ clap_param_value value,
+ char *display,
+ uint32_t size) noexcept {
+ return false;
+ }
+ virtual bool
+ paramsTextToValue(clap_id param_id, const char *display, clap_param_value *value) 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 *note_name) noexcept { return false; }
+
+ //------------------------//
+ // clap_plugin_event_loop //
+ //------------------------//
+ virtual bool implementsEventLoop() const noexcept { return false; }
+ virtual void eventLoopOnTimer(clap_id timer_id) noexcept {}
+ virtual void eventLoopOnFd(clap_fd fd, uint32_t flags) noexcept {}
+
+ //-----------------//
+ // clap_plugin_gui //
+ //-----------------//
+ virtual bool implementsGui() const noexcept { return false; }
+ virtual void guiSize(int32_t *width, int32_t *height) noexcept {}
+ virtual void guiSetScale(double scale) noexcept {}
+ virtual void guiShow() noexcept {}
+ virtual void guiHide() noexcept {}
+ virtual void guiClose() noexcept {}
+
+ //---------------------//
+ // clap_plugin_gui_x11 //
+ //---------------------//
+ virtual bool implementsGuiX11() const noexcept { return false; }
+ virtual bool guiX11Attach(const char *display_name, unsigned long window) noexcept;
+
+ //-----------------------//
+ // clap_plugin_gui_win32 //
+ //-----------------------//
+ virtual bool implementsGuiWin32() const noexcept { return false; }
+ virtual bool guiWin32Attach(clap_hwnd window) noexcept;
+
+ //-----------------------//
+ // clap_plugin_gui_cocoa //
+ //-----------------------//
+ virtual bool implementsGuiCocoa() const noexcept { return false; }
+ virtual bool guiCocoaAttach(void *nsView) noexcept;
+
+ //-------------------------------//
+ // clap_plugin_gui_free_standing //
+ //-------------------------------//
+ virtual bool implementsGuiFreeStanding() const noexcept { return false; }
+ virtual bool guiFreeStandingOpen() noexcept;
+
+ //////////////////
+ // Invalidation //
+ //////////////////
+ void invalidateAudioPortsDefinition();
+
+ /////////////
+ // 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()); }
+
+ /////////////////////////////////
+ // Interface consistency check //
+ /////////////////////////////////
+ bool canUseHostLog() const noexcept;
+ bool canUseThreadCheck() const noexcept;
+ bool canUseTrackInfo() const noexcept;
+ bool canUseState() const noexcept;
+ bool canChangeAudioPorts() const noexcept;
+
+ /////////////////////
+ // Thread Checking //
+ /////////////////////
+ void checkMainThread() const noexcept;
+ void ensureMainThread(const char *method) const noexcept;
+ void ensureAudioThread(const char *method) const noexcept;
+
+ ///////////////
+ // Utilities //
+ ///////////////
+ static Plugin &from(const clap_plugin *plugin) noexcept;
+
+ 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;
+
+ virtual bool isValidParamId(clap_id param_id) const 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_;
+ }
+
+ protected:
+ const clap_host *const host_ = nullptr;
+ const clap_host_log *hostLog_ = nullptr;
+ const clap_host_thread_check *hostThreadCheck_ = nullptr;
+ const clap_host_thread_pool *hostThreadPool_ = nullptr;
+ const clap_host_audio_ports *hostAudioPorts_ = nullptr;
+ const clap_host_event_filter *hostEventFilter_ = nullptr;
+ const clap_host_file_reference *hostFileReference_ = nullptr;
+ const clap_host_latency *hostLatency_ = nullptr;
+ const clap_host_gui *hostGui_ = nullptr;
+ const clap_host_event_loop *hostEventLoop_ = nullptr;
+ const clap_host_params *hostParams_ = nullptr;
+ const clap_host_track_info *hostTrackInfo_ = nullptr;
+ const clap_host_state *hostState_ = nullptr;
+ const clap_host_note_name *hostNoteName_ = nullptr;
+
+ 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, int sample_rate) 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 clap_process_status clapProcess(const clap_plugin *plugin,
+ const clap_process *process) 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_render
+ static void 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, clap_ostream *stream) noexcept;
+ static bool clapStateLoad(const clap_plugin *plugin, clap_istream *stream) noexcept;
+ static bool clapStateIsDirty(const clap_plugin *plugin) 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 clapParamsIinfo(const clap_plugin *plugin,
+ int32_t param_index,
+ clap_param_info *param_info) noexcept;
+ static bool clapParamsEnumValue(const clap_plugin *plugin,
+ clap_id param_id,
+ int32_t value_index,
+ clap_param_value *value) noexcept;
+ static bool clapParamsValue(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value *value) noexcept;
+ static bool clapParamsSetValue(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value value,
+ clap_param_value modulation) noexcept;
+ static bool clapParamsValueToText(const clap_plugin *plugin,
+ clap_id param_id,
+ clap_param_value value,
+ char *display,
+ uint32_t size) noexcept;
+ static bool clapParamsTextToValue(const clap_plugin *plugin,
+ clap_id param_id,
+ const char *display,
+ clap_param_value *value) 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_event_loop
+ static void clapEventLoopOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept;
+ static void clapEventLoopOnFd(const clap_plugin *plugin, clap_fd fd, uint32_t flags) noexcept;
+
+ // clap_plugin_gui
+ static void clapGuiSize(const clap_plugin *plugin, int32_t *width, int32_t *height) noexcept;
+ static void clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept;
+ static void clapGuiShow(const clap_plugin *plugin) noexcept;
+ static void clapGuiHide(const clap_plugin *plugin) noexcept;
+ static void clapGuiClose(const clap_plugin *plugin) noexcept;
+
+ // clap_plugin_gui_x11
+ static bool clapGuiX11Attach(const clap_plugin *plugin,
+ const char *display_name,
+ unsigned long window) noexcept;
+
+ // clap_plugin_gui_win32
+ static bool clapGuiWin32Attach(const clap_plugin *plugin, clap_hwnd window) noexcept;
+
+ // clap_plugin_gui_cocoa
+ static bool clapGuiCocoaAttach(const clap_plugin *plugin, void *nsView) noexcept;
+
+ // clap_plugin_gui_free_standing
+ static bool clapGuiFreeStandingOpen(const clap_plugin *plugin) noexcept;
+
+ // interfaces
+ static const constexpr clap_plugin_render pluginRender_ = {
+ clapRenderSetMode,
+ };
+
+ static const constexpr clap_plugin_thread_pool pluginThreadPool_ = {
+ clapThreadPoolExec,
+ };
+
+ static const constexpr clap_plugin_state pluginState_ = {
+ clapStateSave,
+ clapStateLoad,
+ clapStateIsDirty,
+ };
+
+ static const constexpr clap_plugin_preset_load pluginPresetLoad_ = {
+ clapPresetLoadFromFile,
+ };
+
+ static const constexpr clap_plugin_track_info pluginTrackInfo_ = {
+ clapTrackInfoChanged,
+ };
+
+ static const constexpr clap_plugin_audio_ports pluginAudioPorts_ = {
+ clapAudioPortsCount,
+ clapAudioPortsInfo,
+ clapAudioPortsConfigCount,
+ clapAudioPortsGetConfig,
+ clapAudioPortsSetConfig,
+ };
+
+ static const constexpr clap_plugin_params pluginParams_ = {
+ clapParamsCount,
+ clapParamsIinfo,
+ clapParamsEnumValue,
+ clapParamsValue,
+ clapParamsSetValue,
+ clapParamsValueToText,
+ clapParamsTextToValue,
+ };
+
+ static const constexpr clap_plugin_latency pluginLatency_ = {
+ clapLatencyGet,
+ };
+
+ static const constexpr clap_plugin_note_name pluginNoteName_ = {
+ clapNoteNameCount,
+ clapNoteNameGet,
+ };
+
+ static const constexpr clap_plugin_event_loop pluginEventLoop_ = {
+ clapEventLoopOnTimer,
+ clapEventLoopOnFd,
+ };
+
+ static const constexpr clap_plugin_gui pluginGui_ = {
+ clapGuiSize,
+ clapGuiSetScale,
+ clapGuiShow,
+ clapGuiHide,
+ clapGuiClose,
+ };
+
+ static const constexpr clap_plugin_gui_x11 pluginGuiX11_ = {
+ clapGuiX11Attach,
+ };
+
+ static const constexpr clap_plugin_gui_win32 pluginGuiWin32_ = {
+ clapGuiWin32Attach,
+ };
+
+ static const constexpr clap_plugin_gui_cocoa pluginGuiCocoa_ = {
+ clapGuiCocoaAttach,
+ };
+
+ static const constexpr clap_plugin_gui_free_standing pluginGuiFreeStanding_ = {
+ clapGuiFreeStandingOpen,
+ };
+
+ // state
+ bool isActive_ = false;
+ bool isProcessing_ = false;
+ int sampleRate_ = 0;
+ };
+} // namespace clap
+\ No newline at end of file
diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt
@@ -1,13 +1,11 @@
add_library(
- clap-plugin SHARED
+ clap-plugins SHARED
clap-entry.cc
parameters.cc
parameters.hh
- plugin.cc
- plugin.hh
plugin-helper.cc
plugin-helper.hh
gain/gain.hh
gain/gain.cc)
-
-set_target_properties(clap-plugin PROPERTIES CXX_STANDARD 20)
+target_link_libraries(clap-plugins clap-plugin-glue)
+set_target_properties(clap-plugins PROPERTIES CXX_STANDARD 20)
diff --git a/examples/plugins/plugin-helper.hh b/examples/plugins/plugin-helper.hh
@@ -1,6 +1,8 @@
#pragma once
-#include "plugin.hh"
+#include <clap-plugin.hh>
+
+#include "parameters.hh"
namespace clap {
class PluginHelper : public Plugin {
diff --git a/examples/plugins/plugin.cc b/examples/plugins/plugin.cc
@@ -1,753 +0,0 @@
-#include <cassert>
-#include <cstring>
-#include <filesystem>
-#include <iostream>
-#include <sstream>
-#include <stdexcept>
-#include <utility>
-
-#include "plugin.hh"
-
-namespace clap {
-
- Plugin::Plugin(const clap_plugin_descriptor *desc, const clap_host *host) : host_(host) {
- plugin_.plugin_data = this;
- plugin_.desc = desc;
- plugin_.init = Plugin::clapInit;
- plugin_.destroy = Plugin::clapDestroy;
- plugin_.extension = nullptr;
- plugin_.process = nullptr;
- plugin_.activate = nullptr;
- plugin_.deactivate = nullptr;
- plugin_.start_processing = nullptr;
- plugin_.stop_processing = nullptr;
- }
-
- /////////////////////
- // CLAP Interfaces //
- /////////////////////
-
- //-------------//
- // clap_plugin //
- //-------------//
- bool Plugin::clapInit(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
-
- self.plugin_.extension = Plugin::clapExtension;
- self.plugin_.process = Plugin::clapProcess;
- self.plugin_.activate = Plugin::clapActivate;
- self.plugin_.deactivate = Plugin::clapDeactivate;
- self.plugin_.start_processing = Plugin::clapStartProcessing;
- self.plugin_.stop_processing = Plugin::clapStopProcessing;
-
- self.initInterfaces();
- self.ensureMainThread("clap_plugin.init");
- return self.init();
- }
-
- void Plugin::clapDestroy(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin.destroy");
- delete &from(plugin);
- }
-
- bool Plugin::clapActivate(const clap_plugin *plugin, int sample_rate) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin.activate");
-
- if (self.isActive_) {
- self.hostMisbehaving("Plugin was activated twice");
-
- if (sample_rate != self.sampleRate_) {
- std::ostringstream msg;
- msg << "The plugin was activated twice and with different sample rates: "
- << self.sampleRate_ << " and " << sample_rate
- << ". The host must deactivate the plugin first." << std::endl
- << "Simulating deactivation.";
- self.hostMisbehaving(msg.str());
- clapDeactivate(plugin);
- }
- }
-
- if (sample_rate <= 0) {
- std::ostringstream msg;
- msg << "The plugin was activated with an invalid sample rates: " << sample_rate;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- assert(!self.isActive_);
- assert(self.sampleRate_ == 0);
-
- if (!self.activate(sample_rate)) {
- assert(!self.isActive_);
- assert(self.sampleRate_ == 0);
- return false;
- }
-
- self.isActive_ = true;
- self.sampleRate_ = sample_rate;
- return true;
- }
-
- void Plugin::clapDeactivate(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin.deactivate");
-
- if (!self.isActive_) {
- self.hostMisbehaving("The plugin was deactivated twice.");
- return;
- }
-
- self.deactivate();
- }
-
- bool Plugin::clapStartProcessing(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureAudioThread("clap_plugin.start_processing");
-
- if (!self.isActive_) {
- self.hostMisbehaving("Host called clap_plugin.start_processing() on a deactivated plugin");
- return false;
- }
-
- if (self.isProcessing_) {
- self.hostMisbehaving("Host called clap_plugin.start_processing() twice");
- return true;
- }
-
- self.isProcessing_ = self.startProcessing();
- return self.isProcessing_;
- }
-
- void Plugin::clapStopProcessing(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureAudioThread("clap_plugin.stop_processing");
-
- if (!self.isActive_) {
- self.hostMisbehaving("Host called clap_plugin.stop_processing() on a deactivated plugin");
- return;
- }
-
- if (!self.isProcessing_) {
- self.hostMisbehaving("Host called clap_plugin.stop_processing() twice");
- return;
- }
-
- self.stopProcessing();
- self.isProcessing_ = false;
- }
-
- clap_process_status Plugin::clapProcess(const clap_plugin *plugin,
- const clap_process *process) noexcept {
- auto &self = from(plugin);
- self.ensureAudioThread("clap_plugin.process");
-
- if (!self.isActive_) {
- self.hostMisbehaving("Host called clap_plugin.process() on a deactivated plugin");
- return CLAP_PROCESS_ERROR;
- }
-
- if (!self.isProcessing_) {
- self.hostMisbehaving(
- "Host called clap_plugin.process() without calling clap_plugin.start_processing()");
- return CLAP_PROCESS_ERROR;
- }
-
- return self.process(process);
- }
-
- const void *Plugin::clapExtension(const clap_plugin *plugin, const char *id) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin.extension");
-
- if (!strcmp(id, CLAP_EXT_STATE) && self.implementsState())
- return &pluginState_;
- if (!strcmp(id, CLAP_EXT_PRESET_LOAD) && self.implementsPresetLoad())
- return &pluginPresetLoad_;
- if (!strcmp(id, CLAP_EXT_RENDER) && self.implementsRender())
- return &pluginRender_;
- if (!strcmp(id, CLAP_EXT_TRACK_INFO) && self.implementsTrackInfo())
- return &pluginTrackInfo_;
- if (!strcmp(id, CLAP_EXT_LATENCY) && self.implementsLatency())
- return &pluginLatency_;
- if (!strcmp(id, CLAP_EXT_AUDIO_PORTS) && self.implementsAudioPorts())
- return &pluginAudioPorts_;
- if (!strcmp(id, CLAP_EXT_PARAMS) && self.implementsParams())
- return &pluginParams_;
- if (!strcmp(id, CLAP_EXT_NOTE_NAME) && self.implementsNoteName())
- return &pluginNoteName_;
- if (!strcmp(id, CLAP_EXT_THREAD_POOL) && self.implementsThreadPool())
- return &pluginThreadPool_;
- if (!strcmp(id, CLAP_EXT_EVENT_LOOP) && self.implementsEventLoop())
- return &pluginEventLoop_;
- if (!strcmp(id, CLAP_EXT_GUI) && self.implementsGui())
- return &pluginGui_;
- if (!strcmp(id, CLAP_EXT_GUI_X11) && self.implementsGuiX11())
- return &pluginGuiX11_;
- if (!strcmp(id, CLAP_EXT_GUI_WIN32) && self.implementsGuiWin32())
- return &pluginGuiWin32_;
- if (!strcmp(id, CLAP_EXT_GUI_COCOA) && self.implementsGuiCocoa())
- return &pluginGuiCocoa_;
- if (!strcmp(id, CLAP_EXT_GUI_FREE_STANDING) && self.implementsGuiFreeStanding())
- return &pluginGuiFreeStanding_;
-
- return from(plugin).extension(id);
- }
-
- template <typename T>
- void Plugin::initInterface(const T *&ptr, const char *id) noexcept {
- assert(!ptr);
- assert(id);
-
- if (host_->extension)
- ptr = static_cast<const T *>(host_->extension(host_, id));
- }
-
- void Plugin::initInterfaces() noexcept {
- initInterface(hostLog_, CLAP_EXT_LOG);
- initInterface(hostThreadCheck_, CLAP_EXT_THREAD_CHECK);
- initInterface(hostThreadPool_, CLAP_EXT_THREAD_POOL);
- initInterface(hostAudioPorts_, CLAP_EXT_AUDIO_PORTS);
- initInterface(hostEventLoop_, CLAP_EXT_EVENT_LOOP);
- initInterface(hostEventFilter_, CLAP_EXT_EVENT_FILTER);
- initInterface(hostFileReference_, CLAP_EXT_FILE_REFERENCE);
- initInterface(hostLatency_, CLAP_EXT_LATENCY);
- initInterface(hostGui_, CLAP_EXT_GUI);
- initInterface(hostParams_, CLAP_EXT_PARAMS);
- initInterface(hostTrackInfo_, CLAP_EXT_TRACK_INFO);
- initInterface(hostState_, CLAP_EXT_STATE);
- initInterface(hostNoteName_, CLAP_EXT_NOTE_NAME);
- }
-
- //-------------------//
- // clap_plugin_state //
- //-------------------//
- uint32_t Plugin::clapLatencyGet(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_latency.get");
-
- return self.latencyGet();
- }
-
- //--------------------//
- // clap_plugin_render //
- //--------------------//
- void Plugin::clapRenderSetMode(const clap_plugin *plugin,
- clap_plugin_render_mode mode) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_render.set_mode");
-
- switch (mode) {
- case CLAP_RENDER_REALTIME:
- case CLAP_RENDER_OFFLINE:
- self.renderSetMode(mode);
- break;
-
- default: {
- std::ostringstream msg;
- msg << "host called clap_plugin_render.set_mode with an unknown mode : " << mode;
- self.hostMisbehaving(msg.str());
- break;
- }
- }
- }
-
- //-------------------------//
- // clap_plugin_thread_pool //
- //-------------------------//
- void Plugin::clapThreadPoolExec(const clap_plugin *plugin, uint32_t task_index) noexcept {
- auto &self = from(plugin);
-
- self.threadPoolExec(task_index);
- }
-
- //-------------------//
- // clap_plugin_state //
- //-------------------//
- bool Plugin::clapStateSave(const clap_plugin *plugin, clap_ostream *stream) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_state.save");
-
- return self.stateSave(stream);
- }
-
- bool Plugin::clapStateLoad(const clap_plugin *plugin, clap_istream *stream) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_state.load");
-
- return self.stateLoad(stream);
- }
-
- bool Plugin::clapStateIsDirty(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_state.is_dirty");
-
- return self.stateIsDirty();
- }
-
- //-------------------------//
- // clap_plugin_preset_load //
- //-------------------------//
- bool Plugin::clapPresetLoadFromFile(const clap_plugin *plugin, const char *path) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_preset_load.from_file");
-
- if (!path) {
- self.hostMisbehaving("host called clap_plugin_preset_load.from_file with a null path");
- return false;
- }
-
- // TODO check if the file is readable
-
- return self.presetLoadFromFile(path);
- }
-
- //------------------------//
- // clap_plugin_track_info //
- //------------------------//
-
- void Plugin::clapTrackInfoChanged(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_track_info.changed");
-
- if (!self.canUseTrackInfo()) {
- self.hostMisbehaving("host called clap_plugin_track_info.changed() but does not provide a "
- "complete clap_host_track_info interface");
- return;
- }
-
- self.trackInfoChanged();
- }
-
- //-------------------------//
- // clap_plugin_audio_ports //
- //-------------------------//
-
- uint32_t Plugin::clapAudioPortsCount(const clap_plugin *plugin, bool is_input) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_audio_ports.count");
-
- return self.audioPortsCount(is_input);
- }
-
- bool Plugin::clapAudioPortsInfo(const clap_plugin *plugin,
- uint32_t index,
- bool is_input,
- clap_audio_port_info *info) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_audio_ports.info");
- auto count = clapAudioPortsCount(plugin, is_input);
- if (index >= count) {
- std::ostringstream msg;
- msg << "Host called clap_plugin_audio_ports.info() with an index out of bounds: " << index
- << " >= " << count;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- return self.audioPortsInfo(index, is_input, info);
- }
-
- uint32_t Plugin::clapAudioPortsConfigCount(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_audio_ports.config_count");
- return self.audioPortsConfigCount();
- }
-
- bool Plugin::clapAudioPortsGetConfig(const clap_plugin *plugin,
- uint32_t index,
- clap_audio_ports_config *config) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_audio_ports.get_config");
-
- auto count = clapAudioPortsConfigCount(plugin);
- if (index >= count) {
- std::ostringstream msg;
- msg << "called clap_plugin_audio_ports.get_config with an index out of bounds: " << index
- << " >= " << count;
- self.hostMisbehaving(msg.str());
- return false;
- }
- return self.audioPortsGetConfig(index, config);
- }
-
- bool Plugin::clapAudioPortsSetConfig(const clap_plugin *plugin, clap_id config_id) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_audio_ports.get_config");
-
- if (self.isActive())
- self.hostMisbehaving(
- "it is illegal to call clap_audio_ports.set_config if the plugin is active");
-
- return self.audioPortsSetConfig(config_id);
- }
-
- uint32_t Plugin::clapParamsCount(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.count");
-
- return self.paramsCount();
- }
-
- //--------------------//
- // clap_plugin_params //
- //--------------------//
- bool Plugin::clapParamsIinfo(const clap_plugin *plugin,
- int32_t param_index,
- clap_param_info *param_info) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.info");
-
- auto count = clapParamsCount(plugin);
- if (param_index >= count) {
- std::ostringstream msg;
- msg << "called clap_plugin_params.info with an index out of bounds: " << param_index
- << " >= " << count;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- return self.paramsInfo(param_index, param_info);
- }
-
- bool Plugin::clapParamsEnumValue(const clap_plugin *plugin,
- clap_id param_id,
- int32_t value_index,
- clap_param_value *value) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.enum_value");
-
- if (!self.isValidParamId(param_id)) {
- std::ostringstream msg;
- msg << "clap_plugin_params.enum_value called with invalid param_id: " << param_id;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- // TODO: check the value index?
-
- return self.paramsEnumValue(param_id, value_index, value);
- }
-
- bool Plugin::clapParamsValue(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value *value) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.value");
-
- if (!self.isValidParamId(param_id)) {
- std::ostringstream msg;
- msg << "clap_plugin_params.value called with invalid param_id: " << param_id;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- // TODO extra checks
-
- return self.paramsValue(param_id, value);
- }
-
- bool Plugin::clapParamsSetValue(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value value,
- clap_param_value modulation) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.set_value");
-
- if (self.isActive_) {
- self.hostMisbehaving(
- "it is forbidden to call clap_plugin_params.set_value() if the plugin is activated");
- return false;
- }
-
- if (!self.isValidParamId(param_id)) {
- std::ostringstream msg;
- msg << "clap_plugin_params.set_value called with invalid param_id: " << param_id;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- // TODO: extra checks
-
- return self.paramsSetValue(param_id, value, modulation);
- }
-
- bool Plugin::clapParamsValueToText(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value value,
- char *display,
- uint32_t size) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.value_to_text");
-
- if (!self.isValidParamId(param_id)) {
- std::ostringstream msg;
- msg << "clap_plugin_params.value_to_text called with invalid param_id: " << param_id;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- // TODO: extra checks
- return self.paramsValueToText(param_id, value, display, size);
- }
-
- bool Plugin::clapParamsTextToValue(const clap_plugin *plugin,
- clap_id param_id,
- const char *display,
- clap_param_value *value) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_params.text_to_value");
-
- if (!self.isValidParamId(param_id)) {
- std::ostringstream msg;
- msg << "clap_plugin_params.text_to_value called with invalid param_id: " << param_id;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- // TODO: extra checks
- return self.paramsTextToValue(param_id, display, value);
- }
-
- bool Plugin::isValidParamId(clap_id param_id) const noexcept {
- checkMainThread();
-
- auto count = paramsCount();
- clap_param_info info;
- for (uint32_t i = 0; i < count; ++i) {
- if (!paramsInfo(i, &info))
- // TODO: fatal error?
- continue;
-
- if (info.id == param_id)
- return true;
- }
- return false;
- }
-
- //-----------------------//
- // clap_plugin_note_name //
- //-----------------------//
-
- uint32_t Plugin::clapNoteNameCount(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_note_name.count");
- return self.noteNameCount();
- }
-
- bool Plugin::clapNoteNameGet(const clap_plugin *plugin,
- uint32_t index,
- clap_note_name *note_name) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_note_name.get");
-
- // TODO check index
- auto count = clapNoteNameCount(plugin);
- if (index >= count) {
- std::ostringstream msg;
- msg << "host called clap_plugin_note_name.get with an index out of bounds: " << index
- << " >= " << count;
- self.hostMisbehaving(msg.str());
- return false;
- }
-
- return self.noteNameGet(index, note_name);
- }
-
- //------------------------//
- // clap_plugin_event_loop //
- //------------------------//
- void Plugin::clapEventLoopOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_event_loop.on_timer");
-
- if (timer_id == CLAP_INVALID_ID) {
- self.hostMisbehaving(
- "Host called clap_plugin_event_loop.on_timer with an invalid timer_id");
- return;
- }
-
- self.eventLoopOnTimer(timer_id);
- }
-
- void Plugin::clapEventLoopOnFd(const clap_plugin *plugin, clap_fd fd, uint32_t flags) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_event_loop.on_fd");
-
- self.eventLoopOnFd(fd, flags);
- }
-
- //-----------------//
- // clap_plugin_gui //
- //-----------------//
- void Plugin::clapGuiSize(const clap_plugin *plugin, int32_t *width, int32_t *height) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui.size");
-
- self.guiSize(width, height);
- }
-
- void Plugin::clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui.set_scale");
-
- self.guiSetScale(scale);
- }
-
- void Plugin::clapGuiShow(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui.show");
-
- self.guiShow();
- }
-
- void Plugin::clapGuiHide(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui.hide");
-
- self.guiHide();
- }
-
- void Plugin::clapGuiClose(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui.close");
-
- self.guiClose();
- }
-
- //---------------------//
- // clap_plugin_gui_x11 //
- //---------------------//
- bool Plugin::clapGuiX11Attach(const clap_plugin *plugin,
- const char *display_name,
- unsigned long window) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui_x11.attach");
-
- return self.guiX11Attach(display_name, window);
- }
-
- //-----------------------//
- // clap_plugin_gui_win32 //
- //-----------------------//
- bool Plugin::clapGuiWin32Attach(const clap_plugin *plugin, clap_hwnd window) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui_win32.attach");
-
- return self.guiWin32Attach(window);
- }
-
- //-----------------------//
- // clap_plugin_gui_cocoa //
- //-----------------------//
- bool Plugin::clapGuiCocoaAttach(const clap_plugin *plugin, void *nsView) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui_cocoa.attach");
-
- return self.guiCocoaAttach(nsView);
- }
-
- //-------------------------------//
- // clap_plugin_gui_free_standing //
- //-------------------------------//
- bool Plugin::clapGuiFreeStandingOpen(const clap_plugin *plugin) noexcept {
- auto &self = from(plugin);
- self.ensureMainThread("clap_plugin_gui_win32.attach");
-
- return self.guiFreeStandingOpen();
- }
-
- /////////////
- // Logging //
- /////////////
- void Plugin::log(clap_log_severity severity, const char *msg) const noexcept {
- if (canUseHostLog())
- hostLog_->log(host_, severity, msg);
- else
- std::clog << msg << std::endl;
- }
-
- void Plugin::hostMisbehaving(const char *msg) const noexcept {
- log(CLAP_LOG_HOST_MISBEHAVING, msg);
- }
-
- /////////////////////////////////
- // Interface consistency check //
- /////////////////////////////////
-
- bool Plugin::canUseHostLog() const noexcept { return hostLog_ && hostLog_->log; }
-
- bool Plugin::canUseThreadCheck() const noexcept {
- return hostThreadCheck_ && hostThreadCheck_->is_audio_thread &&
- hostThreadCheck_->is_main_thread;
- }
-
- /////////////////////
- // Thread Checking //
- /////////////////////
-
- void Plugin::checkMainThread() const noexcept {
- if (!hostThreadCheck_ || !hostThreadCheck_->is_main_thread ||
- hostThreadCheck_->is_main_thread(host_))
- return;
-
- std::terminate();
- }
-
- void Plugin::ensureMainThread(const char *method) const noexcept {
- if (!hostThreadCheck_ || !hostThreadCheck_->is_main_thread ||
- hostThreadCheck_->is_main_thread(host_))
- return;
-
- std::ostringstream msg;
- msg << "Host called the method " << method
- << "() on wrong thread! It must be called on main thread!";
- hostMisbehaving(msg.str());
- std::terminate();
- }
-
- void Plugin::ensureAudioThread(const char *method) const noexcept {
- if (!hostThreadCheck_ || !hostThreadCheck_->is_audio_thread ||
- hostThreadCheck_->is_audio_thread(host_))
- return;
-
- std::ostringstream msg;
- msg << "Host called the method " << method
- << "() on wrong thread! It must be called on audio thread!";
- hostMisbehaving(msg.str());
- std::terminate();
- }
-
- ///////////////
- // Utilities //
- ///////////////
- Plugin &Plugin::from(const clap_plugin *plugin) noexcept {
- if (!plugin) {
- std::cerr << "called with a null clap_plugin pointer!" << std::endl;
- std::terminate();
- }
-
- if (!plugin->plugin_data) {
- std::cerr << "called with a null clap_plugin->plugin_data pointer! The host must never "
- "change this pointer!"
- << std::endl;
- std::terminate();
- }
-
- return *static_cast<Plugin *>(plugin->plugin_data);
- }
-
- uint32_t Plugin::compareAudioPortsInfo(const clap_audio_port_info &a,
- const clap_audio_port_info &b) noexcept {
- if (a.sample_size != b.sample_size || a.in_place != b.in_place || a.is_cv != b.is_cv ||
- a.is_main != b.is_main || a.channel_count != b.channel_count ||
- a.channel_map != b.channel_map || a.id != b.id)
- return CLAP_AUDIO_PORTS_RESCAN_ALL;
-
- if (strncmp(a.name, b.name, sizeof(a.name)))
- return CLAP_AUDIO_PORTS_RESCAN_NAMES;
-
- return 0;
- }
-} // namespace clap
-\ No newline at end of file
diff --git a/examples/plugins/plugin.hh b/examples/plugins/plugin.hh
@@ -1,442 +0,0 @@
-#pragma once
-
-#include <cassert>
-#include <string>
-#include <string_view>
-#include <vector>
-
-#include <clap/all.h>
-
-#include "parameters.hh"
-
-namespace clap {
- /// @brief C++ glue and checks
- ///
- /// @note for an higher level implementation, see @ref PluginHelper
- 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(int sampleRate) 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 const void *extension(const char *id) noexcept { return nullptr; }
-
- //---------------------//
- // clap_plugin_latenxy //
- //---------------------//
- virtual bool implementsLatency() const noexcept { return false; }
- virtual uint32_t latencyGet() const noexcept { return 0; }
-
- //--------------------//
- // clap_plugin_render //
- //--------------------//
- virtual bool implementsRender() const noexcept { return false; }
- virtual void renderSetMode(clap_plugin_render_mode mode) noexcept {}
-
- //-------------------------//
- // clap_plugin_thread_pool //
- //-------------------------//
- virtual bool implementsThreadPool() const noexcept { return false; }
- virtual void threadPoolExec(uint32_t task_index) noexcept;
-
- //-------------------//
- // clap_plugin_state //
- //-------------------//
- virtual bool implementsState() const noexcept { return false; }
- virtual bool stateSave(clap_ostream *stream) noexcept { return false; }
- virtual bool stateLoad(clap_istream *stream) noexcept { return false; }
- virtual bool stateIsDirty() const noexcept { return false; }
- void stateMarkDirty() const noexcept {
- if (canUseState())
- hostState_->mark_dirty(host_);
- }
-
- //-------------------------//
- // 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 is_input) const noexcept { return 0; }
- virtual bool
- audioPortsInfo(uint32_t index, bool is_input, 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 config_id) noexcept { return false; }
-
- //--------------------//
- // clap_plugin_params //
- //--------------------//
- virtual bool implementsParams() const noexcept { return false; }
- virtual uint32_t paramsCount() const noexcept { return 0; }
- virtual bool paramsInfo(int32_t paramIndex, clap_param_info *info) const noexcept {
- return false;
- }
- virtual bool
- paramsEnumValue(clap_id paramId, int32_t valueIndex, clap_param_value *value) noexcept {
- return false;
- }
- virtual bool paramsValue(clap_id paramId, clap_param_value *value) noexcept { return false; }
- virtual bool paramsSetValue(clap_id paramId,
- clap_param_value value,
- clap_param_value modulation) noexcept {
- return false;
- }
- virtual bool paramsValueToText(clap_id paramId,
- clap_param_value value,
- char *display,
- uint32_t size) noexcept {
- return false;
- }
- virtual bool
- paramsTextToValue(clap_id param_id, const char *display, clap_param_value *value) 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 *note_name) noexcept { return false; }
-
- //------------------------//
- // clap_plugin_event_loop //
- //------------------------//
- virtual bool implementsEventLoop() const noexcept { return false; }
- virtual void eventLoopOnTimer(clap_id timer_id) noexcept {}
- virtual void eventLoopOnFd(clap_fd fd, uint32_t flags) noexcept {}
-
- //-----------------//
- // clap_plugin_gui //
- //-----------------//
- virtual bool implementsGui() const noexcept { return false; }
- virtual void guiSize(int32_t *width, int32_t *height) noexcept {}
- virtual void guiSetScale(double scale) noexcept {}
- virtual void guiShow() noexcept {}
- virtual void guiHide() noexcept {}
- virtual void guiClose() noexcept {}
-
- //---------------------//
- // clap_plugin_gui_x11 //
- //---------------------//
- virtual bool implementsGuiX11() const noexcept { return false; }
- virtual bool guiX11Attach(const char *display_name, unsigned long window) noexcept;
-
- //-----------------------//
- // clap_plugin_gui_win32 //
- //-----------------------//
- virtual bool implementsGuiWin32() const noexcept { return false; }
- virtual bool guiWin32Attach(clap_hwnd window) noexcept;
-
- //-----------------------//
- // clap_plugin_gui_cocoa //
- //-----------------------//
- virtual bool implementsGuiCocoa() const noexcept { return false; }
- virtual bool guiCocoaAttach(void *nsView) noexcept;
-
- //-------------------------------//
- // clap_plugin_gui_free_standing //
- //-------------------------------//
- virtual bool implementsGuiFreeStanding() const noexcept { return false; }
- virtual bool guiFreeStandingOpen() noexcept;
-
- //////////////////
- // Invalidation //
- //////////////////
- void invalidateAudioPortsDefinition();
-
- /////////////
- // 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()); }
-
- /////////////////////////////////
- // Interface consistency check //
- /////////////////////////////////
- bool canUseHostLog() const noexcept;
- bool canUseThreadCheck() const noexcept;
- bool canUseTrackInfo() const noexcept;
- bool canUseState() const noexcept;
- bool canChangeAudioPorts() const noexcept;
-
- /////////////////////
- // Thread Checking //
- /////////////////////
- void checkMainThread() const noexcept;
- void ensureMainThread(const char *method) const noexcept;
- void ensureAudioThread(const char *method) const noexcept;
-
- ///////////////
- // Utilities //
- ///////////////
- static Plugin &from(const clap_plugin *plugin) noexcept;
-
- 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;
-
- virtual bool isValidParamId(clap_id param_id) const 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_;
- }
-
- protected:
- const clap_host *const host_ = nullptr;
- const clap_host_log *hostLog_ = nullptr;
- const clap_host_thread_check *hostThreadCheck_ = nullptr;
- const clap_host_thread_pool *hostThreadPool_ = nullptr;
- const clap_host_audio_ports *hostAudioPorts_ = nullptr;
- const clap_host_event_filter *hostEventFilter_ = nullptr;
- const clap_host_file_reference *hostFileReference_ = nullptr;
- const clap_host_latency *hostLatency_ = nullptr;
- const clap_host_gui *hostGui_ = nullptr;
- const clap_host_event_loop *hostEventLoop_ = nullptr;
- const clap_host_params *hostParams_ = nullptr;
- const clap_host_track_info *hostTrackInfo_ = nullptr;
- const clap_host_state *hostState_ = nullptr;
- const clap_host_note_name *hostNoteName_ = nullptr;
-
- 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, int sample_rate) 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 clap_process_status clapProcess(const clap_plugin *plugin,
- const clap_process *process) 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_render
- static void 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, clap_ostream *stream) noexcept;
- static bool clapStateLoad(const clap_plugin *plugin, clap_istream *stream) noexcept;
- static bool clapStateIsDirty(const clap_plugin *plugin) 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 clapParamsIinfo(const clap_plugin *plugin,
- int32_t param_index,
- clap_param_info *param_info) noexcept;
- static bool clapParamsEnumValue(const clap_plugin *plugin,
- clap_id param_id,
- int32_t value_index,
- clap_param_value *value) noexcept;
- static bool clapParamsValue(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value *value) noexcept;
- static bool clapParamsSetValue(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value value,
- clap_param_value modulation) noexcept;
- static bool clapParamsValueToText(const clap_plugin *plugin,
- clap_id param_id,
- clap_param_value value,
- char *display,
- uint32_t size) noexcept;
- static bool clapParamsTextToValue(const clap_plugin *plugin,
- clap_id param_id,
- const char *display,
- clap_param_value *value) 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_event_loop
- static void clapEventLoopOnTimer(const clap_plugin *plugin, clap_id timer_id) noexcept;
- static void clapEventLoopOnFd(const clap_plugin *plugin, clap_fd fd, uint32_t flags) noexcept;
-
- // clap_plugin_gui
- static void clapGuiSize(const clap_plugin *plugin, int32_t *width, int32_t *height) noexcept;
- static void clapGuiSetScale(const clap_plugin *plugin, double scale) noexcept;
- static void clapGuiShow(const clap_plugin *plugin) noexcept;
- static void clapGuiHide(const clap_plugin *plugin) noexcept;
- static void clapGuiClose(const clap_plugin *plugin) noexcept;
-
- // clap_plugin_gui_x11
- static bool clapGuiX11Attach(const clap_plugin *plugin,
- const char *display_name,
- unsigned long window) noexcept;
-
- // clap_plugin_gui_win32
- static bool clapGuiWin32Attach(const clap_plugin *plugin, clap_hwnd window) noexcept;
-
- // clap_plugin_gui_cocoa
- static bool clapGuiCocoaAttach(const clap_plugin *plugin, void *nsView) noexcept;
-
- // clap_plugin_gui_free_standing
- static bool clapGuiFreeStandingOpen(const clap_plugin *plugin) noexcept;
-
- // interfaces
- static const constexpr clap_plugin_render pluginRender_ = {
- clapRenderSetMode,
- };
-
- static const constexpr clap_plugin_thread_pool pluginThreadPool_ = {
- clapThreadPoolExec,
- };
-
- static const constexpr clap_plugin_state pluginState_ = {
- clapStateSave,
- clapStateLoad,
- clapStateIsDirty,
- };
-
- static const constexpr clap_plugin_preset_load pluginPresetLoad_ = {
- clapPresetLoadFromFile,
- };
-
- static const constexpr clap_plugin_track_info pluginTrackInfo_ = {
- clapTrackInfoChanged,
- };
-
- static const constexpr clap_plugin_audio_ports pluginAudioPorts_ = {
- clapAudioPortsCount,
- clapAudioPortsInfo,
- clapAudioPortsConfigCount,
- clapAudioPortsGetConfig,
- clapAudioPortsSetConfig,
- };
-
- static const constexpr clap_plugin_params pluginParams_ = {
- clapParamsCount,
- clapParamsIinfo,
- clapParamsEnumValue,
- clapParamsValue,
- clapParamsSetValue,
- clapParamsValueToText,
- clapParamsTextToValue,
- };
-
- static const constexpr clap_plugin_latency pluginLatency_ = {
- clapLatencyGet,
- };
-
- static const constexpr clap_plugin_note_name pluginNoteName_ = {
- clapNoteNameCount,
- clapNoteNameGet,
- };
-
- static const constexpr clap_plugin_event_loop pluginEventLoop_ = {
- clapEventLoopOnTimer,
- clapEventLoopOnFd,
- };
-
- static const constexpr clap_plugin_gui pluginGui_ = {
- clapGuiSize,
- clapGuiSetScale,
- clapGuiShow,
- clapGuiHide,
- clapGuiClose,
- };
-
- static const constexpr clap_plugin_gui_x11 pluginGuiX11_ = {
- clapGuiX11Attach,
- };
-
- static const constexpr clap_plugin_gui_win32 pluginGuiWin32_ = {
- clapGuiWin32Attach,
- };
-
- static const constexpr clap_plugin_gui_cocoa pluginGuiCocoa_ = {
- clapGuiCocoaAttach,
- };
-
- static const constexpr clap_plugin_gui_free_standing pluginGuiFreeStanding_ = {
- clapGuiFreeStandingOpen,
- };
-
- // state
- bool isActive_ = false;
- bool isProcessing_ = false;
- int sampleRate_ = 0;
- };
-} // namespace clap
-\ No newline at end of file