Initial commit

This commit is contained in:
Patrick 2025-10-03 20:16:11 +02:00
commit 56f7cd1875
105 changed files with 22109 additions and 0 deletions

View file

@ -0,0 +1,63 @@
#pragma once
#include "../plugin.h"
// This extension can be used to specify the channel mapping used by the plugin.
static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC[] = "clap.ambisonic/3";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC_COMPAT[] = "clap.ambisonic.draft/3";
static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic";
#ifdef __cplusplus
extern "C" {
#endif
enum clap_ambisonic_ordering {
// FuMa channel ordering
CLAP_AMBISONIC_ORDERING_FUMA = 0,
// ACN channel ordering
CLAP_AMBISONIC_ORDERING_ACN = 1,
};
enum clap_ambisonic_normalization {
CLAP_AMBISONIC_NORMALIZATION_MAXN = 0,
CLAP_AMBISONIC_NORMALIZATION_SN3D = 1,
CLAP_AMBISONIC_NORMALIZATION_N3D = 2,
CLAP_AMBISONIC_NORMALIZATION_SN2D = 3,
CLAP_AMBISONIC_NORMALIZATION_N2D = 4,
};
typedef struct clap_ambisonic_config {
uint32_t ordering; // see clap_ambisonic_ordering
uint32_t normalization; // see clap_ambisonic_normalization
} clap_ambisonic_config_t;
typedef struct clap_plugin_ambisonic {
// Returns true if the given configuration is supported.
// [main-thread]
bool(CLAP_ABI *is_config_supported)(const clap_plugin_t *plugin,
const clap_ambisonic_config_t *config);
// Returns true on success
// [main-thread]
bool(CLAP_ABI *get_config)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
clap_ambisonic_config_t *config);
} clap_plugin_ambisonic_t;
typedef struct clap_host_ambisonic {
// Informs the host that the info has changed.
// The info can only change when the plugin is de-activated.
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_ambisonic_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,64 @@
#pragma once
#include "../plugin.h"
/// @page Audio Ports Activation
///
/// This extension provides a way for the host to activate and de-activate audio ports.
/// Deactivating a port provides the following benefits:
/// - the plugin knows ahead of time that a given input is not present and can choose
/// an optimized computation path,
/// - the plugin knows that an output is not consumed by the host, and doesn't need to
/// compute it.
///
/// Audio ports can only be activated or deactivated when the plugin is deactivated, unless
/// can_activate_while_processing() returns true.
///
/// Audio buffers must still be provided if the audio port is deactivated.
/// In such case, they shall be filled with 0 (or whatever is the neutral value in your context)
/// and the constant_mask shall be set.
///
/// Audio ports are initially in the active state after creating the plugin instance.
/// Audio ports state are not saved in the plugin state, so the host must restore the
/// audio ports state after creating the plugin instance.
///
/// Audio ports state is invalidated by clap_plugin_audio_ports_config.select() and
/// clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_LIST).
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_ACTIVATION[] =
"clap.audio-ports-activation/2";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_ACTIVATION_COMPAT[] =
"clap.audio-ports-activation/draft-2";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_audio_ports_activation {
// Returns true if the plugin supports activation/deactivation while processing.
// [main-thread]
bool(CLAP_ABI *can_activate_while_processing)(const clap_plugin_t *plugin);
// Activate the given port.
//
// It is only possible to activate and de-activate on the audio-thread if
// can_activate_while_processing() returns true.
//
// sample_size indicate if the host will provide 32 bit audio buffers or 64 bits one.
// Possible values are: 32, 64 or 0 if unspecified.
//
// returns false if failed, or invalid parameters
// [active ? audio-thread : main-thread]
bool(CLAP_ABI *set_active)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
bool is_active,
uint32_t sample_size);
} clap_plugin_audio_ports_activation_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,109 @@
#pragma once
#include "../string-sizes.h"
#include "../plugin.h"
#include "audio-ports.h"
/// @page Audio Ports Config
///
/// This extension let the plugin provide port configurations presets.
/// For example mono, stereo, surround, ambisonic, ...
///
/// After the plugin initialization, the host may scan the list of configurations and eventually
/// select one that fits the plugin context. The host can only select a configuration if the plugin
/// is deactivated.
///
/// A configuration is a very simple description of the audio ports:
/// - it describes the main input and output ports
/// - it has a name that can be displayed to the user
///
/// The idea behind the configurations, is to let the user choose one via a menu.
///
/// Plugins with very complex configuration possibilities should let the user configure the ports
/// from the plugin GUI, and call @ref clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_ALL).
///
/// To inquire the exact bus layout, the plugin implements the clap_plugin_audio_ports_config_info_t
/// extension where all busses can be retrieved in the same way as in the audio-port extension.
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG[] = "clap.audio-ports-config";
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG_INFO[] =
"clap.audio-ports-config-info/1";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_CONFIG_INFO_COMPAT[] =
"clap.audio-ports-config-info/draft-0";
#ifdef __cplusplus
extern "C" {
#endif
// Minimalistic description of ports configuration
typedef struct clap_audio_ports_config {
clap_id id;
char name[CLAP_NAME_SIZE];
uint32_t input_port_count;
uint32_t output_port_count;
// main input info
bool has_main_input;
uint32_t main_input_channel_count;
const char *main_input_port_type;
// main output info
bool has_main_output;
uint32_t main_output_channel_count;
const char *main_output_port_type;
} clap_audio_ports_config_t;
// The audio ports config scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_audio_ports_config {
// Gets the number of available configurations
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Gets information about a configuration
// Returns true on success and stores the result into config.
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
uint32_t index,
clap_audio_ports_config_t *config);
// Selects the configuration designated by id
// Returns true if the configuration could be applied.
// Once applied the host should scan again the audio ports.
// [main-thread & plugin-deactivated]
bool(CLAP_ABI *select)(const clap_plugin_t *plugin, clap_id config_id);
} clap_plugin_audio_ports_config_t;
// Extended config info
typedef struct clap_plugin_audio_ports_config_info {
// Gets the id of the currently selected config, or CLAP_INVALID_ID if the current port
// layout isn't part of the config list.
//
// [main-thread]
clap_id(CLAP_ABI *current_config)(const clap_plugin_t *plugin);
// Get info about an audio port, for a given config_id.
// This is analogous to clap_plugin_audio_ports.get().
// Returns true on success and stores the result into info.
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
clap_id config_id,
uint32_t port_index,
bool is_input,
clap_audio_port_info_t *info);
} clap_plugin_audio_ports_config_info_t;
typedef struct clap_host_audio_ports_config {
// Rescan the full list of configs.
// [main-thread]
void(CLAP_ABI *rescan)(const clap_host_t *host);
} clap_host_audio_ports_config_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,116 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
/// @page Audio Ports
///
/// This extension provides a way for the plugin to describe its current audio ports.
///
/// If the plugin does not implement this extension, it won't have audio ports.
///
/// 32 bits support is required for both host and plugins. 64 bits audio is optional.
///
/// The plugin is only allowed to change its ports configuration while it is deactivated.
static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS[] = "clap.audio-ports";
static CLAP_CONSTEXPR const char CLAP_PORT_MONO[] = "mono";
static CLAP_CONSTEXPR const char CLAP_PORT_STEREO[] = "stereo";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// This port is the main audio input or output.
// There can be only one main input and main output.
// Main port must be at index 0.
CLAP_AUDIO_PORT_IS_MAIN = 1 << 0,
// This port can be used with 64 bits audio
CLAP_AUDIO_PORT_SUPPORTS_64BITS = 1 << 1,
// 64 bits audio is preferred with this port
CLAP_AUDIO_PORT_PREFERS_64BITS = 1 << 2,
// This port must be used with the same sample size as all the other ports which have this flag.
// In other words if all ports have this flag then the plugin may either be used entirely with
// 64 bits audio or 32 bits audio, but it can't be mixed.
CLAP_AUDIO_PORT_REQUIRES_COMMON_SAMPLE_SIZE = 1 << 3,
};
typedef struct clap_audio_port_info {
// id identifies a port and must be stable.
// id may overlap between input and output ports.
clap_id id;
char name[CLAP_NAME_SIZE]; // displayable name
uint32_t flags;
uint32_t channel_count;
// If null or empty then it is unspecified (arbitrary audio).
// This field can be compared against:
// - CLAP_PORT_MONO
// - CLAP_PORT_STEREO
// - CLAP_PORT_SURROUND (defined in the surround extension)
// - CLAP_PORT_AMBISONIC (defined in the ambisonic extension)
//
// An extension can provide its own port type and way to inspect the channels.
const char *port_type;
// in-place processing: allow the host to use the same buffer for input and output
// if supported set the pair port id.
// if not supported set to CLAP_INVALID_ID
clap_id in_place_pair;
} clap_audio_port_info_t;
// The audio ports scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_audio_ports {
// Number of ports, for either input or output
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input);
// Get info about an audio port.
// Returns true on success and stores the result into info.
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
uint32_t index,
bool is_input,
clap_audio_port_info_t *info);
} clap_plugin_audio_ports_t;
enum {
// The ports name did change, the host can scan them right away.
CLAP_AUDIO_PORTS_RESCAN_NAMES = 1 << 0,
// [!active] The flags did change
CLAP_AUDIO_PORTS_RESCAN_FLAGS = 1 << 1,
// [!active] The channel_count did change
CLAP_AUDIO_PORTS_RESCAN_CHANNEL_COUNT = 1 << 2,
// [!active] The port type did change
CLAP_AUDIO_PORTS_RESCAN_PORT_TYPE = 1 << 3,
// [!active] The in-place pair did change, this requires.
CLAP_AUDIO_PORTS_RESCAN_IN_PLACE_PAIR = 1 << 4,
// [!active] The list of ports have changed: entries have been removed/added.
CLAP_AUDIO_PORTS_RESCAN_LIST = 1 << 5,
};
typedef struct clap_host_audio_ports {
// Checks if the host allows a plugin to change a given aspect of the audio ports definition.
// [main-thread]
bool(CLAP_ABI *is_rescan_flag_supported)(const clap_host_t *host, uint32_t flag);
// Rescan the full list of audio ports according to the flags.
// It is illegal to ask the host to rescan with a flag that is not supported.
// Certain flags require the plugin to be de-activated.
// [main-thread]
void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags);
} clap_host_audio_ports_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,63 @@
#pragma once
#include "audio-ports.h"
#ifdef __cplusplus
extern "C" {
#endif
// This extension lets the host configure the plugin's input and output audio ports.
// This is a "push" approach to audio ports configuration.
static CLAP_CONSTEXPR const char CLAP_EXT_CONFIGURABLE_AUDIO_PORTS[] =
"clap.configurable-audio-ports/1";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_CONFIGURABLE_AUDIO_PORTS_COMPAT[] =
"clap.configurable-audio-ports.draft1";
typedef struct clap_audio_port_configuration_request {
// Identifies the port by is_input and port_index
bool is_input;
uint32_t port_index;
// The requested number of channels.
uint32_t channel_count;
// The port type, see audio-ports.h, clap_audio_port_info.port_type for interpretation.
const char *port_type;
// cast port_details according to port_type:
// - CLAP_PORT_MONO: (discard)
// - CLAP_PORT_STEREO: (discard)
// - CLAP_PORT_SURROUND: const uint8_t *channel_map
// - CLAP_PORT_AMBISONIC: const clap_ambisonic_config_t *info
const void *port_details;
} clap_audio_port_configuration_request_t;
typedef struct clap_plugin_configurable_audio_ports {
// Returns true if the given configurations can be applied using apply_configuration().
// [main-thread && !active]
bool(CLAP_ABI *can_apply_configuration)(
const clap_plugin_t *plugin,
const struct clap_audio_port_configuration_request *requests,
uint32_t request_count);
// Submit a bunch of configuration requests which will atomically be applied together,
// or discarded together.
//
// Once the configuration is successfully applied, it isn't necessary for the plugin to call
// clap_host_audio_ports->changed(); and it isn't necessary for the host to scan the
// audio ports.
//
// Returns true if applied.
// [main-thread && !active]
bool(CLAP_ABI *apply_configuration)(const clap_plugin_t *plugin,
const struct clap_audio_port_configuration_request *requests,
uint32_t request_count);
} clap_plugin_configurable_audio_ports_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,167 @@
#pragma once
#include "../plugin.h"
// This extension lets the host and plugin exchange menu items and let the plugin ask the host to
// show its context menu.
static CLAP_CONSTEXPR const char CLAP_EXT_CONTEXT_MENU[] = "clap.context-menu/1";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_CONTEXT_MENU_COMPAT[] = "clap.context-menu.draft/0";
#ifdef __cplusplus
extern "C" {
#endif
// There can be different target kind for a context menu
enum {
CLAP_CONTEXT_MENU_TARGET_KIND_GLOBAL = 0,
CLAP_CONTEXT_MENU_TARGET_KIND_PARAM = 1,
};
// Describes the context menu target
typedef struct clap_context_menu_target {
uint32_t kind;
clap_id id;
} clap_context_menu_target_t;
enum {
// Adds a clickable menu entry.
// data: const clap_context_menu_item_entry_t*
CLAP_CONTEXT_MENU_ITEM_ENTRY,
// Adds a clickable menu entry which will feature both a checkmark and a label.
// data: const clap_context_menu_item_check_entry_t*
CLAP_CONTEXT_MENU_ITEM_CHECK_ENTRY,
// Adds a separator line.
// data: NULL
CLAP_CONTEXT_MENU_ITEM_SEPARATOR,
// Starts a sub menu with the given label.
// data: const clap_context_menu_item_begin_submenu_t*
CLAP_CONTEXT_MENU_ITEM_BEGIN_SUBMENU,
// Ends the current sub menu.
// data: NULL
CLAP_CONTEXT_MENU_ITEM_END_SUBMENU,
// Adds a title entry
// data: const clap_context_menu_item_title_t *
CLAP_CONTEXT_MENU_ITEM_TITLE,
};
typedef uint32_t clap_context_menu_item_kind_t;
typedef struct clap_context_menu_entry {
// text to be displayed
const char *label;
// if false, then the menu entry is greyed out and not clickable
bool is_enabled;
clap_id action_id;
} clap_context_menu_entry_t;
typedef struct clap_context_menu_check_entry {
// text to be displayed
const char *label;
// if false, then the menu entry is greyed out and not clickable
bool is_enabled;
// if true, then the menu entry will be displayed as checked
bool is_checked;
clap_id action_id;
} clap_context_menu_check_entry_t;
typedef struct clap_context_menu_item_title {
// text to be displayed
const char *title;
// if false, then the menu entry is greyed out
bool is_enabled;
} clap_context_menu_item_title_t;
typedef struct clap_context_menu_submenu {
// text to be displayed
const char *label;
// if false, then the menu entry is greyed out and won't show submenu
bool is_enabled;
} clap_context_menu_submenu_t;
// Context menu builder.
// This object isn't thread-safe and must be used on the same thread as it was provided.
typedef struct clap_context_menu_builder {
void *ctx;
// Adds an entry to the menu.
// item_data type is determined by item_kind.
// Returns true on success.
bool(CLAP_ABI *add_item)(const struct clap_context_menu_builder *builder,
clap_context_menu_item_kind_t item_kind,
const void *item_data);
// Returns true if the menu builder supports the given item kind
bool(CLAP_ABI *supports)(const struct clap_context_menu_builder *builder,
clap_context_menu_item_kind_t item_kind);
} clap_context_menu_builder_t;
typedef struct clap_plugin_context_menu {
// Insert plugin's menu items into the menu builder.
// If target is null, assume global context.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *populate)(const clap_plugin_t *plugin,
const clap_context_menu_target_t *target,
const clap_context_menu_builder_t *builder);
// Performs the given action, which was previously provided to the host via populate().
// If target is null, assume global context.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *perform)(const clap_plugin_t *plugin,
const clap_context_menu_target_t *target,
clap_id action_id);
} clap_plugin_context_menu_t;
typedef struct clap_host_context_menu {
// Insert host's menu items into the menu builder.
// If target is null, assume global context.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *populate)(const clap_host_t *host,
const clap_context_menu_target_t *target,
const clap_context_menu_builder_t *builder);
// Performs the given action, which was previously provided to the plugin via populate().
// If target is null, assume global context.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *perform)(const clap_host_t *host,
const clap_context_menu_target_t *target,
clap_id action_id);
// Returns true if the host can display a popup menu for the plugin.
// This may depend upon the current windowing system used to display the plugin, so the
// return value is invalidated after creating the plugin window.
// [main-thread]
bool(CLAP_ABI *can_popup)(const clap_host_t *host);
// Shows the host popup menu for a given parameter.
// If the plugin is using embedded GUI, then x and y are relative to the plugin's window,
// otherwise they're absolute coordinate, and screen index might be set accordingly.
// If target is null, assume global context.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *popup)(const clap_host_t *host,
const clap_context_menu_target_t *target,
int32_t screen_index,
int32_t x,
int32_t y);
} clap_host_context_menu_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,33 @@
#pragma once
#include "../audio-ports.h"
#ifdef __cplusplus
extern "C" {
#endif
// This extension lets the host add and remove audio ports to the plugin.
static CLAP_CONSTEXPR const char CLAP_EXT_EXTENSIBLE_AUDIO_PORTS[] =
"clap.extensible-audio-ports/1";
typedef struct clap_plugin_extensible_audio_ports {
// Asks the plugin to add a new port (at the end of the list), with the following settings.
// port_type: see clap_audio_port_info.port_type for interpretation.
// port_details: see clap_audio_port_configuration_request.port_details for interpretation.
// Returns true on success.
// [main-thread && !is_active]
bool(CLAP_ABI *add_port)(const clap_plugin_t *plugin,
bool is_input,
uint32_t channel_count,
const char *port_type,
const void *port_details);
// Asks the plugin to remove a port.
// Returns true on success.
// [main-thread && !is_active]
bool(CLAP_ABI *remove_port)(const clap_plugin_t *plugin, bool is_input, uint32_t index);
} clap_plugin_extensible_audio_ports_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,34 @@
#pragma once
#include "../../plugin.h"
// This extension lets the plugin report the current gain adjustment
// (typically, gain reduction) to the host.
static CLAP_CONSTEXPR const char CLAP_EXT_GAIN_ADJUSTMENT_METERING[] = "clap.gain-adjustment-metering/0";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_gain_adjustment_metering {
// Returns the current gain adjustment in dB. The value is intended
// for informational display, for example in a host meter or tooltip.
// The returned value represents the gain adjustment that the plugin
// applied to the last sample in the most recently processed block.
//
// The returned value is in dB. Zero means the plugin is applying no gain
// reduction, or is not processing. A negative value means the plugin is
// applying gain reduction, as with a compressor or limiter. A positive
// value means the plugin is adding gain, as with an expander. The value
// represents the dynamic gain reduction or expansion applied by the
// plugin, before any make-up gain or other adjustment. A single value is
// returned for all audio channels.
//
// [audio-thread]
double(CLAP_ABI *get)(const clap_plugin_t *plugin);
} clap_plugin_gain_adjustment_metering_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,153 @@
#pragma once
#include "../../plugin.h"
// This extension allows a host to render a small curve provided by the plugin.
// A useful application is to render an EQ frequency response in the DAW mixer view.
static CLAP_CONSTEXPR const char CLAP_EXT_MINI_CURVE_DISPLAY[] = "clap.mini-curve-display/3";
#ifdef __cplusplus
extern "C" {
#endif
enum clap_mini_curve_display_curve_kind {
// If the curve's kind doesn't fit in any proposed kind, use this one
// and perhaps, make a pull request to extend the list.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_UNSPECIFIED = 0,
// The mini curve is intended to draw the total gain response of the plugin.
// In this case the y values are in dB and the x values are in Hz (logarithmic).
// This would be useful in for example an equalizer.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_GAIN_RESPONSE = 1,
// The mini curve is intended to draw the total phase response of the plugin.
// In this case the y values are in radians and the x values are in Hz (logarithmic).
// This would be useful in for example an equalizer.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_PHASE_RESPONSE = 2,
// The mini curve is intended to draw the transfer curve of the plugin.
// In this case the both x and y values are in dB.
// This would be useful in for example a compressor or distortion plugin.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_TRANSFER_CURVE = 3,
// This mini curve is intended to draw gain reduction over time. In this case
// x refers to the window in seconds and y refers to level in dB, x_min is
// always 0, and x_max would be the duration of the window.
// This would be useful in for example a compressor or limiter.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_GAIN_REDUCTION = 4,
// This curve is intended as a generic time series plot. In this case
// x refers to the window in seconds. x_min is always 0, and x_max would be the duration of the
// window.
// Y is not specified and up to the plugin.
CLAP_MINI_CURVE_DISPLAY_CURVE_KIND_TIME_SERIES = 5,
// Note: more entries could be added here in the future
};
typedef struct clap_mini_curve_display_curve_hints {
// Range for the x axis.
double x_min;
double x_max;
// Range for the y axis.
double y_min;
double y_max;
} clap_mini_curve_display_curve_hints_t;
// A set of points representing the curve to be painted.
typedef struct clap_mini_curve_display_curve_data {
// Indicates the kind of curve those values represent, the host can use this
// information to paint the curve using a meaningful color.
int32_t curve_kind;
// values[0] will be the leftmost value and values[data_size -1] will be the rightmost
// value.
//
// The value 0 and UINT16_MAX won't be painted.
// The value 1 will be at the bottom of the curve and UINT16_MAX - 1 will be at the top.
uint16_t *values;
uint32_t values_count;
} clap_mini_curve_display_curve_data_t;
typedef struct clap_plugin_mini_curve_display {
// Returns the number of curves the plugin wants to paint.
// Be aware that the space to display those curves will be small, and too much data will make
// the output hard to read.
uint32_t(CLAP_ABI *get_curve_count)(const clap_plugin_t *plugin);
// Renders the curve into each the curves buffer.
//
// curves is an array, and each entries (up to curves_size) contains pre-allocated
// values buffer that must be filled by the plugin.
//
// The host will "stack" the curves, from the first one to the last one.
// curves[0] is the first curve to be painted.
// curves[n + 1] will be painted over curves[n].
//
// Returns the number of curves rendered.
// [main-thread]
uint32_t(CLAP_ABI *render)(const clap_plugin_t *plugin,
clap_mini_curve_display_curve_data_t *curves,
uint32_t curves_size);
// Tells the plugin if the curve is currently observed or not.
// When it isn't observed render() can't be called.
//
// When is_obseverd becomes true, the curve content and axis name are implicitly invalidated. So
// the plugin don't need to call host->changed.
//
// [main-thread]
void(CLAP_ABI *set_observed)(const clap_plugin_t *plugin, bool is_observed);
// Retrives the axis name.
// x_name and y_name must not to be null.
// Returns true on success, if the name capacity was sufficient.
// [main-thread]
bool(CLAP_ABI *get_axis_name)(const clap_plugin_t *plugin,
uint32_t curve_index,
char *x_name,
char *y_name,
uint32_t name_capacity);
} clap_plugin_mini_curve_display_t;
enum clap_mini_curve_display_change_flags {
// Informs the host that the curve content changed.
// Can only be called if the curve is observed and is static.
CLAP_MINI_CURVE_DISPLAY_CURVE_CHANGED = 1 << 0,
// Informs the host that the curve axis name changed.
// Can only be called if the curve is observed.
CLAP_MINI_CURVE_DISPLAY_AXIS_NAME_CHANGED = 1 << 1,
};
typedef struct clap_host_mini_curve_display {
// Fills in the given clap_mini_display_curve_hints_t structure and returns
// true if successful. If not, return false.
// [main-thread]
bool(CLAP_ABI *get_hints)(const clap_host_t *host,
uint32_t kind,
clap_mini_curve_display_curve_hints_t *hints);
// Mark the curve as being static or dynamic.
// The curve is initially considered as static, though the plugin should explicitely
// initialize this state.
//
// When static, the curve changes will be notified by calling host->changed().
// When dynamic, the curve is constantly changing and the host is expected to
// periodically re-render.
//
// [main-thread]
void(CLAP_ABI *set_dynamic)(const clap_host_t *host, bool is_dynamic);
// See clap_mini_curve_display_change_flags
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host, uint32_t flags);
} clap_host_mini_curve_display_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,108 @@
#pragma once
#include "../../color.h"
#include "../../plugin.h"
#include "../../string-sizes.h"
// This extension allows a host to tell the plugin more about its position
// within a project or session.
static CLAP_CONSTEXPR const char CLAP_EXT_PROJECT_LOCATION[] = "clap.project-location/2";
#ifdef __cplusplus
extern "C" {
#endif
enum clap_project_location_kind {
// Represents a document/project/session.
CLAP_PROJECT_LOCATION_PROJECT = 1,
// Represents a group of tracks.
// It can contain track groups, tracks, and devices (post processing).
// The first device within a track group has the index of
// the last track or track group within this group + 1.
CLAP_PROJECT_LOCATION_TRACK_GROUP = 2,
// Represents a single track.
// It contains devices (serial).
CLAP_PROJECT_LOCATION_TRACK = 3,
// Represents a single device.
// It can contain other nested device chains.
CLAP_PROJECT_LOCATION_DEVICE = 4,
// Represents a nested device chain (serial).
// Its parent must be a device.
// It contains other devices.
CLAP_PROJECT_LOCATION_NESTED_DEVICE_CHAIN = 5,
};
enum clap_project_location_track_kind {
// This track is an instrument track.
CLAP_PROJECT_LOCATION_INSTUMENT_TRACK = 1,
// This track is an audio track.
CLAP_PROJECT_LOCATION_AUDIO_TRACK = 2,
// This track is both an instrument and audio track.
CLAP_PROJECT_LOCATION_HYBRID_TRACK = 3,
// This track is a return track.
CLAP_PROJECT_LOCATION_RETURN_TRACK = 4,
// This track is a master track.
// Each group have a master track for processing the sum of all its children tracks.
CLAP_PROJECT_LOCATION_MASTER_TRACK = 5,
};
enum clap_project_location_flags {
CLAP_PROJECT_LOCATION_HAS_INDEX = 1 << 0,
CLAP_PROJECT_LOCATION_HAS_COLOR = 1 << 1,
};
typedef struct clap_project_location_element {
// A bit-mask, see clap_project_location_flags.
uint64_t flags;
// Kind of the element, must be one of the CLAP_PROJECT_LOCATION_* values.
uint32_t kind;
// Only relevant if kind is CLAP_PLUGIN_LOCATION_TRACK.
// see enum CLAP_PROJECT_LOCATION_track_kind.
uint32_t track_kind;
// Index within the parent element.
// Only usable if CLAP_PROJECT_LOCATION_HAS_INDEX is set in flags.
uint32_t index;
// Internal ID of the element.
// This is not intended for display to the user,
// but rather to give the host a potential quick way for lookups.
char id[CLAP_PATH_SIZE];
// User friendly name of the element.
char name[CLAP_NAME_SIZE];
// Color for this element.
// Only usable if CLAP_PROJECT_LOCATION_HAS_COLOR is set in flags.
clap_color_t color;
} clap_project_location_element_t;
typedef struct clap_plugin_project_location {
// Called by the host when the location of the plugin instance changes.
//
// The last item in this array always refers to the device itself, and as
// such is expected to be of kind CLAP_PLUGIN_LOCATION_DEVICE.
// The first item in this array always refers to the project this device is in and must be of
// kind CLAP_PROJECT_LOCATION_PROJECT. The path is expected to be something like: PROJECT >
// TRACK_GROUP+ > TRACK > (DEVICE > NESTED_DEVICE_CHAIN)* > DEVICE
//
// [main-thread]
void(CLAP_ABI *set)(const clap_plugin_t *plugin,
const clap_project_location_element_t *path,
uint32_t num_elements);
} clap_plugin_project_location_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,88 @@
#pragma once
#include "../../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_RESOURCE_DIRECTORY[] = "clap.resource-directory/1";
#ifdef __cplusplus
extern "C" {
#endif
/// @page Resource Directory
///
/// This extension provides a way for the plugin to store its resources as file in a directory
/// provided by the host and recover them later on.
///
/// The plugin **must** store relative path in its state toward resource directories.
///
/// Resource sharing:
/// - shared directory is shared among all plugin instances, hence mostly appropriate for read-only
/// content
/// -> suitable for read-only content
/// - exclusive directory is exclusive to the plugin instance
/// -> if the plugin, then its exclusive directory must be duplicated too
/// -> suitable for read-write content
///
/// Keeping the shared directory clean:
/// - to avoid clashes in the shared directory, plugins are encouraged to organize their files in
/// sub-folders, for example create one subdirectory using the vendor name
/// - don't use symbolic links or hard links which points outside of the directory
///
/// Resource life-time:
/// - exclusive folder content is managed by the plugin instance
/// - exclusive folder content is deleted when the plugin instance is removed from the project
/// - shared folder content isn't managed by the host, until all plugins using the shared directory
/// are removed from the project
///
/// Note for the host
/// - try to use the filesystem's copy-on-write feature when possible for reducing exclusive folder
/// space usage on duplication
/// - host can "garbage collect" the files in the shared folder using:
/// clap_plugin_resource_directory.get_files_count()
/// clap_plugin_resource_directory.get_file_path()
/// but be **very** careful before deleting any resources
typedef struct clap_plugin_resource_directory {
// Sets the directory in which the plugin can save its resources.
// The directory remains valid until it is overridden or the plugin is destroyed.
// If path is null or blank, it clears the directory location.
// path must be absolute.
// [main-thread]
void(CLAP_ABI *set_directory)(const clap_plugin_t *plugin, const char *path, bool is_shared);
// Asks the plugin to put its resources into the resource directory.
// It is not necessary to collect files which belongs to the plugin's
// factory content unless the param all is true.
// [main-thread]
void(CLAP_ABI *collect)(const clap_plugin_t *plugin, bool all);
// Returns the number of files used by the plugin in the shared resource folder.
// [main-thread]
uint32_t(CLAP_ABI *get_files_count)(const clap_plugin_t *plugin);
// Retrieves relative file path to the resource directory.
// @param path writable memory to store the path
// @param path_size number of available bytes in path
// Returns the number of bytes in the path, or -1 on error
// [main-thread]
int32_t(CLAP_ABI *get_file_path)(const clap_plugin_t *plugin,
uint32_t index,
char *path,
uint32_t path_size);
} clap_plugin_resource_directory_t;
typedef struct clap_host_resource_directory {
// Request the host to setup a resource directory with the specified sharing.
// Returns true if the host will perform the request.
// [main-thread]
bool(CLAP_ABI *request_directory)(const clap_host_t *host, bool is_shared);
// Tell the host that the resource directory of the specified sharing is no longer required.
// If is_shared = false, then the host may delete the directory content.
// [main-thread]
void(CLAP_ABI *release_directory)(const clap_host_t *host, bool is_shared);
} clap_host_resource_directory_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,90 @@
#pragma once
#include "../../plugin.h"
// This extension lets the plugin request "scratch" memory from the host.
//
// The scratch memory is thread-local, and can be accessed during
// `clap_plugin->process()` and `clap_plugin_thread_pool->exec()`;
// its content is not persistent between callbacks.
//
// The motivation for this extension is to allow the plugin host
// to "share" a single scratch buffer across multiple plugin
// instances.
//
// For example, imagine the host needs to process N plugins
// in sequence, and each plugin requires 10K of scratch memory.
// If each plugin pre-allocates its own scratch memory, then N * 10K
// of memory is being allocated in total. However, if each plugin
// requests 10K of scratch memory from the host, then the host can
// allocate a single 10K scratch buffer, and make it available to all
// plugins.
//
// This optimization may allow for reduced memory usage and improved
// CPU cache usage.
static CLAP_CONSTEXPR const char CLAP_EXT_SCRATCH_MEMORY[] = "clap.scratch-memory/1";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_host_scratch_memory {
// Asks the host to reserve scratch memory.
//
// The plugin may call this method multiple times (for
// example, gradually decreasing the amount of scratch
// being asked for until the host returns true), however,
// the plugin should avoid calling this method un-neccesarily
// since the host implementation may be relatively expensive.
// If the plugin calls `reserve()` multiple times, then the
// last call invalidates all previous calls.
//
// De-activating the plugin releases the scratch memory.
//
// `max_concurrency_hint` is an optional hint which indicates
// the maximum number of threads concurrently accessing the scratch memory.
// Set to 0 if unspecified.
//
// Returns true on success.
//
// [main-thread & being-activated]
bool(CLAP_ABI *reserve)(const clap_host_t *host,
uint32_t scratch_size_bytes,
uint32_t max_concurrency_hint);
// Returns a pointer to the "thread-local" scratch memory.
//
// If the scratch memory wasn't successfully reserved, returns NULL.
//
// If the plugin crosses `max_concurrency_hint`, then the return value
// is either NULL or a valid scratch memory pointer.
//
// This method may only be called by the plugin from the audio thread,
// (i.e. during the process() or thread_pool.exec() callback), and
// the provided memory is only valid until the plugin returns from
// that callback. The plugin must not hold any references to data
// that lives in the scratch memory after returning from the callback,
// as that data will likely be over-written by another plugin using
// the same scratch memory.
//
// The provided memory is not initialized, and may have been used
// by other plugin instances, so the plugin must correctly initialize
// the memory when using it.
//
// The provided memory is owned by the host, so the plugin must not
// free the memory.
//
// If the plugin wants to share the same scratch memory pointer with
// many threads, it must access the the scratch at the beginning of the
// `process()` callback, cache the returned pointer before calling
// `clap_host_thread_pool->request_exec()` and clear the cached pointer
// before returning from `process()`.
//
// [audio-thread]
void *(CLAP_ABI *access)(const clap_host_t *host);
} clap_host_scratch_memory_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,66 @@
#pragma once
#include "../../plugin.h"
// This extension lets the plugin submit transport requests to the host.
// The host has no obligation to execute these requests, so the interface may be
// partially working.
static CLAP_CONSTEXPR const char CLAP_EXT_TRANSPORT_CONTROL[] = "clap.transport-control/1";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_host_transport_control {
// Jumps back to the start point and starts the transport
// [main-thread]
void(CLAP_ABI *request_start)(const clap_host_t *host);
// Stops the transport, and jumps to the start point
// [main-thread]
void(CLAP_ABI *request_stop)(const clap_host_t *host);
// If not playing, starts the transport from its current position
// [main-thread]
void(CLAP_ABI *request_continue)(const clap_host_t *host);
// If playing, stops the transport at the current position
// [main-thread]
void(CLAP_ABI *request_pause)(const clap_host_t *host);
// Equivalent to what "space bar" does with most DAWs
// [main-thread]
void(CLAP_ABI *request_toggle_play)(const clap_host_t *host);
// Jumps the transport to the given position.
// Does not start the transport.
// [main-thread]
void(CLAP_ABI *request_jump)(const clap_host_t *host, clap_beattime position);
// Sets the loop region
// [main-thread]
void(CLAP_ABI *request_loop_region)(const clap_host_t *host,
clap_beattime start,
clap_beattime duration);
// Toggles looping
// [main-thread]
void(CLAP_ABI *request_toggle_loop)(const clap_host_t *host);
// Enables/Disables looping
// [main-thread]
void(CLAP_ABI *request_enable_loop)(const clap_host_t *host, bool is_enabled);
// Enables/Disables recording
// [main-thread]
void(CLAP_ABI *request_record)(const clap_host_t *host, bool is_recording);
// Toggles recording
// [main-thread]
void(CLAP_ABI *request_toggle_record)(const clap_host_t *host);
} clap_host_transport_control_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,144 @@
#pragma once
#include "../../plugin.h"
#include "../../events.h"
#include "../../string-sizes.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TRIGGERS[] = "clap.triggers/1";
#ifdef __cplusplus
extern "C" {
#endif
/// @page Trigger events
///
/// This extension enables the plugin to expose a set of triggers to the host.
///
/// Some examples for triggers:
/// - trigger an envelope which is independent of the notes
/// - trigger a sample-and-hold unit (maybe even per-voice)
enum {
// Does this trigger support per note automations?
CLAP_TRIGGER_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 0,
// Does this trigger support per key automations?
CLAP_TRIGGER_IS_AUTOMATABLE_PER_KEY = 1 << 1,
// Does this trigger support per channel automations?
CLAP_TRIGGER_IS_AUTOMATABLE_PER_CHANNEL = 1 << 2,
// Does this trigger support per port automations?
CLAP_TRIGGER_IS_AUTOMATABLE_PER_PORT = 1 << 3,
};
typedef uint32_t clap_trigger_info_flags;
// Given that this extension is still draft, it'll use the event-registry and its own event
// namespace until we stabilize it.
//
// #include <clap/ext/event-registry.h>
//
// uint16_t CLAP_EXT_TRIGGER_EVENT_SPACE_ID = UINT16_MAX;
// if (host_event_registry->query(host, CLAP_EXT_TRIGGERS, &CLAP_EXT_TRIGGER_EVENT_SPACE_ID)) {
// /* we can use trigger events */
// }
//
// /* later on */
// clap_event_trigger ev;
// ev.header.space_id = CLAP_EXT_TRIGGER_EVENT_SPACE_ID;
// ev.header.type = CLAP_EVENT_TRIGGER;
enum { CLAP_EVENT_TRIGGER = 0 };
typedef struct clap_event_trigger {
clap_event_header_t header;
// target trigger
clap_id trigger_id; // @ref clap_trigger_info.id
void *cookie; // @ref clap_trigger_info.cookie
// target a specific note_id, port, key and channel, -1 for global
int32_t note_id;
int16_t port_index;
int16_t channel;
int16_t key;
} clap_event_trigger_t;
/* This describes a trigger */
typedef struct clap_trigger_info {
// stable trigger identifier, it must never change.
clap_id id;
clap_trigger_info_flags flags;
// in analogy to clap_param_info.cookie
void *cookie;
// displayable name
char name[CLAP_NAME_SIZE];
// the module path containing the trigger, eg:"sequencers/seq1"
// '/' will be used as a separator to show a tree like structure.
char module[CLAP_PATH_SIZE];
} clap_trigger_info_t;
typedef struct clap_plugin_triggers {
// Returns the number of triggers.
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Copies the trigger's info to trigger_info and returns true on success.
// [main-thread]
bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin,
uint32_t index,
clap_trigger_info_t *trigger_info);
} clap_plugin_triggers_t;
enum {
// The trigger info did change, use this flag for:
// - name change
// - module change
// New info takes effect immediately.
CLAP_TRIGGER_RESCAN_INFO = 1 << 0,
// Invalidates everything the host knows about triggers.
// It can only be used while the plugin is deactivated.
// If the plugin is activated use clap_host->restart() and delay any change until the host calls
// clap_plugin->deactivate().
//
// You must use this flag if:
// - some triggers were added or removed.
// - some triggers had critical changes:
// - is_per_note (flag)
// - is_per_key (flag)
// - is_per_channel (flag)
// - is_per_port (flag)
// - cookie
CLAP_TRIGGER_RESCAN_ALL = 1 << 1,
};
typedef uint32_t clap_trigger_rescan_flags;
enum {
// Clears all possible references to a trigger
CLAP_TRIGGER_CLEAR_ALL = 1 << 0,
// Clears all automations to a trigger
CLAP_TRIGGER_CLEAR_AUTOMATIONS = 1 << 1,
};
typedef uint32_t clap_trigger_clear_flags;
typedef struct clap_host_triggers {
// Rescan the full list of triggers according to the flags.
// [main-thread]
void(CLAP_ABI *rescan)(const clap_host_t *host, clap_trigger_rescan_flags flags);
// Clears references to a trigger.
// [main-thread]
void(CLAP_ABI *clear)(const clap_host_t *host,
clap_id trigger_id,
clap_trigger_clear_flags flags);
} clap_host_triggers_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,76 @@
#pragma once
#include "../../plugin.h"
#include "../../events.h"
#include "../../string-sizes.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TUNING[] = "clap.tuning/2";
#ifdef __cplusplus
extern "C" {
#endif
// Use clap_host_event_registry->query(host, CLAP_EXT_TUNING, &space_id) to know the event space.
//
// This event defines the tuning to be used on the given port/channel.
typedef struct clap_event_tuning {
clap_event_header_t header;
int16_t port_index; // -1 global
int16_t channel; // 0..15, -1 global
clap_id tunning_id;
} clap_event_tuning_t;
typedef struct clap_tuning_info {
clap_id tuning_id;
char name[CLAP_NAME_SIZE];
bool is_dynamic; // true if the values may vary with time
} clap_tuning_info_t;
typedef struct clap_plugin_tuning {
// Called when a tuning is added or removed from the pool.
// [main-thread]
void(CLAP_ABI *changed)(const clap_plugin_t *plugin);
} clap_plugin_tuning_t;
// This extension provides a dynamic tuning table to the plugin.
typedef struct clap_host_tuning {
// Gets the relative tuning in semitones against equal temperament with A4=440Hz.
// The plugin may query the tuning at a rate that makes sense for *low* frequency modulations.
//
// If the tuning_id is not found or equals to CLAP_INVALID_ID,
// then the function shall gracefully return a sensible value.
//
// sample_offset is the sample offset from the beginning of the current process block.
//
// should_play(...) should be checked before calling this function.
//
// [audio-thread & in-process]
double(CLAP_ABI *get_relative)(const clap_host_t *host,
clap_id tuning_id,
int32_t channel,
int32_t key,
uint32_t sample_offset);
// Returns true if the note should be played.
// [audio-thread & in-process]
bool(CLAP_ABI *should_play)(const clap_host_t *host,
clap_id tuning_id,
int32_t channel,
int32_t key);
// Returns the number of tunings in the pool.
// [main-thread]
uint32_t(CLAP_ABI *get_tuning_count)(const clap_host_t *host);
// Gets info about a tuning
// Returns true on success and stores the result into info.
// [main-thread]
bool(CLAP_ABI *get_info)(const clap_host_t *host,
uint32_t tuning_index,
clap_tuning_info_t *info);
} clap_host_tuning_t;
#ifdef __cplusplus
}
#endif

201
tests/clap/ext/draft/undo.h Normal file
View file

@ -0,0 +1,201 @@
#pragma once
#include "../../plugin.h"
#include "../../stream.h"
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO[] = "clap.undo/4";
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_CONTEXT[] = "clap.undo_context/4";
static CLAP_CONSTEXPR const char CLAP_EXT_UNDO_DELTA[] = "clap.undo_delta/4";
#ifdef __cplusplus
extern "C" {
#endif
/// @page Undo
///
/// This extension enables the plugin to merge its undo history with the host.
/// This leads to a single undo history shared by the host and many plugins.
///
/// Calling host->undo() or host->redo() is equivalent to clicking undo/redo within the host's GUI.
///
/// If the plugin uses this interface then its undo and redo should be entirely delegated to
/// the host; clicking in the plugin's UI undo or redo is equivalent to clicking undo or redo in the
/// host's UI.
///
/// Some changes are long running changes, for example a mouse interaction will begin editing some
/// complex data and it may take multiple events and a long duration to complete the change.
/// In such case the plugin will call host->begin_change() to indicate the beginning of a long
/// running change and complete the change by calling host->change_made().
///
/// The host may group changes together:
/// [---------------------------------]
/// ^-T0 ^-T1 ^-T2 ^-T3
/// Here a long running change C0 begin at T0.
/// A instantaneous change C1 at T1, and another one C2 at T2.
/// Then at T3 the long running change is completed.
/// The host will then create a single undo step that will merge all the changes into C0.
///
/// This leads to another important consideration: starting a long running change without
/// terminating is **VERY BAD**, because while a change is running it is impossible to call undo or
/// redo.
///
/// Rationale: multiple designs were considered and this one has the benefit of having a single undo
/// history. This simplifies the host implementation, leading to less bugs, a more robust design
/// and maybe an easier experience for the user because there's a single undo context versus one
/// for the host and one for each plugin instance.
///
/// This extension tries to make it as easy as possible for the plugin to hook into the host undo
/// and make it efficient when possible by using deltas. The plugin interfaces are all optional, and
/// the plugin can for a minimal implementation, just use the host interface and call
/// host->change_made() without providing a delta. This is enough for the host to know that it can
/// capture a plugin state for the undo step.
typedef struct clap_undo_delta_properties {
// If true, then the plugin will provide deltas in host->change_made().
// If false, then all clap_undo_delta_properties's attributes become irrelevant.
bool has_delta;
// If true, then the deltas can be stored on disk and re-used in the future as long as the plugin
// is compatible with the given format_version.
//
// If false, then format_version must be set to CLAP_INVALID_ID.
bool are_deltas_persistent;
// This represents the delta format version that the plugin is currently using.
// Use CLAP_INVALID_ID for invalid value.
clap_id format_version;
} clap_undo_delta_properties_t;
// Use CLAP_EXT_UNDO_DELTA.
// This is an optional interface, using deltas is an optimization versus making a state snapshot.
typedef struct clap_plugin_undo_delta {
// Asks the plugin the delta properties.
// [main-thread]
void(CLAP_ABI *get_delta_properties)(const clap_plugin_t *plugin,
clap_undo_delta_properties_t *properties);
// Asks the plugin if it can apply a delta using the given format version.
// Returns true if it is possible.
// [main-thread]
bool(CLAP_ABI *can_use_delta_format_version)(const clap_plugin_t *plugin,
clap_id format_version);
// Undo using the delta.
// Returns true on success.
//
// [main-thread]
bool(CLAP_ABI *undo)(const clap_plugin_t *plugin,
clap_id format_version,
const void *delta,
size_t delta_size);
// Redo using the delta.
// Returns true on success.
//
// [main-thread]
bool(CLAP_ABI *redo)(const clap_plugin_t *plugin,
clap_id format_version,
const void *delta,
size_t delta_size);
} clap_plugin_undo_delta_t;
// Use CLAP_EXT_UNDO_CONTEXT.
// This is an optional interface, that the plugin can implement in order to know about
// the current undo context.
typedef struct clap_plugin_undo_context {
// Indicate if it is currently possible to perform an undo or redo operation.
// [main-thread & plugin-subscribed-to-undo-context]
void(CLAP_ABI *set_can_undo)(const clap_plugin_t *plugin, bool can_undo);
void(CLAP_ABI *set_can_redo)(const clap_plugin_t *plugin, bool can_redo);
// Sets the name of the next undo or redo step.
// name: null terminated string.
// [main-thread & plugin-subscribed-to-undo-context]
void(CLAP_ABI *set_undo_name)(const clap_plugin_t *plugin, const char *name);
void(CLAP_ABI *set_redo_name)(const clap_plugin_t *plugin, const char *name);
} clap_plugin_undo_context_t;
// Use CLAP_EXT_UNDO.
typedef struct clap_host_undo {
// Begins a long running change.
// The plugin must not call this twice: there must be either a call to cancel_change() or
// change_made() before calling begin_change() again.
// [main-thread]
void(CLAP_ABI *begin_change)(const clap_host_t *host);
// Cancels a long running change.
// cancel_change() must not be called without a preceding begin_change().
// [main-thread]
void(CLAP_ABI *cancel_change)(const clap_host_t *host);
// Completes an undoable change.
// At the moment of this function call, plugin_state->save() would include the current change.
//
// name: mandatory null terminated string describing the change, this is displayed to the user
//
// delta: optional, it is a binary blobs used to perform the undo and redo. When not available
// the host will save the plugin state and use state->load() to perform undo and redo.
// The plugin must be able to perform a redo operation using the delta, though the undo operation
// is only possible if delta_can_undo is true.
//
// Note: the provided delta may be used for incremental state saving and crash recovery. The
// plugin can indicate a format version id and the validity lifetime for the binary blobs.
// The host can use these to verify the compatibility before applying the delta.
// If the plugin is unable to use a delta, a notification should be provided to the user and
// the crash recovery should perform a best effort job, at least restoring the latest saved
// state.
//
// Special case: for objects with shared and synchronized state, changes shouldn't be reported
// as the host already knows about it.
// For example, plugin parameter changes shouldn't produce a call to change_made().
//
// Note: if the plugin asked for this interface, then host_state->mark_dirty() will not create an
// implicit undo step.
//
// Note: if the plugin did load a preset or did something that leads to a large delta,
// it may consider not producing a delta (pass null) and let the host make a state snapshot
// instead.
//
// Note: if a plugin is producing a lot of changes within a small amount of time, the host
// may merge them into a single undo step.
//
// [main-thread]
void(CLAP_ABI *change_made)(const clap_host_t *host,
const char *name,
const void *delta,
size_t delta_size,
bool delta_can_undo);
// Asks the host to perform the next undo or redo step.
//
// Note: this maybe a complex and asynchronous operation, which may complete after
// this function returns.
//
// Note: the host may ignore this request if there is no undo/redo step to perform,
// or if the host is unable to perform undo/redo at the time (eg: a long running
// change is going on).
//
// [main-thread]
void(CLAP_ABI *request_undo)(const clap_host_t *host);
void(CLAP_ABI *request_redo)(const clap_host_t *host);
// Subscribes to or unsubscribes from undo context info.
//
// This method helps reducing the number of calls the host has to perform when updating
// the undo context info. Consider a large project with 1000+ plugins, we don't want to
// call 1000+ times update, while the plugin may only need the context info if its GUI
// is shown and it wants to display undo/redo info.
//
// Initial state is unsubscribed.
//
// is_subscribed: set to true to receive context info
//
// It is mandatory for the plugin to implement CLAP_EXT_UNDO_CONTEXT when using this method.
//
// [main-thread]
void(CLAP_ABI *set_wants_context_updates)(const clap_host_t *host, bool is_subscribed);
} clap_host_undo_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,22 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_EVENT_REGISTRY[] = "clap.event-registry";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_host_event_registry {
// Queries an event space id.
// The space id 0 is reserved for CLAP's core events. See CLAP_CORE_EVENT_SPACE.
//
// Return false and sets *space_id to UINT16_MAX if the space name is unknown to the host.
// [main-thread]
bool(CLAP_ABI *query)(const clap_host_t *host, const char *space_name, uint16_t *space_id);
} clap_host_event_registry_t;
#ifdef __cplusplus
}
#endif

244
tests/clap/ext/gui.h Normal file
View file

@ -0,0 +1,244 @@
#pragma once
#include "../plugin.h"
/// @page GUI
///
/// This extension defines how the plugin will present its GUI.
///
/// There are two approaches:
/// 1. the plugin creates a window and embeds it into the host's window
/// 2. the plugin creates a floating window
///
/// Embedding the window gives more control to the host, and feels more integrated.
/// Floating window are sometimes the only option due to technical limitations.
///
/// The Embedding protocol is by far the most common, supported by all hosts to date,
/// and a plugin author should support at least that case.
///
/// Showing the GUI works as follow:
/// 1. clap_plugin_gui->is_api_supported(), check what can work
/// 2. clap_plugin_gui->create(), allocates gui resources
/// 3. if the plugin window is floating
/// 4. -> clap_plugin_gui->set_transient()
/// 5. -> clap_plugin_gui->suggest_title()
/// 6. else
/// 7. -> clap_plugin_gui->set_scale()
/// 8. -> clap_plugin_gui->can_resize()
/// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size()
/// 10. -> else clap_plugin_gui->get_size(), gets initial size
/// 11. -> clap_plugin_gui->set_parent()
/// 12. clap_plugin_gui->show()
/// 13. clap_plugin_gui->hide()/show() ...
/// 14. clap_plugin_gui->destroy() when done with the gui
///
/// Resizing the window (initiated by the plugin, if embedded):
/// 1. Plugins calls clap_host_gui->request_resize()
/// 2. If the host returns true the new size is accepted,
/// the host doesn't have to call clap_plugin_gui->set_size().
/// If the host returns false, the new size is rejected.
///
/// Resizing the window (drag, if embedded)):
/// 1. Only possible if clap_plugin_gui->can_resize() returns true
/// 2. Mouse drag -> new_size
/// 3. clap_plugin_gui->adjust_size(new_size) -> working_size
/// 4. clap_plugin_gui->set_size(working_size)
static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui";
// If your windowing API is not listed here, please open an issue and we'll figure it out.
// https://github.com/free-audio/clap/issues/new
// uses physical size
// embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent
static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32";
// uses logical size, don't call clap_plugin_gui->set_scale()
static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa";
// uses physical size
// embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11";
// uses physical size
// embed is currently not supported, use floating windows
static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland";
#ifdef __cplusplus
extern "C" {
#endif
typedef void *clap_hwnd;
typedef void *clap_nsview;
typedef unsigned long clap_xwnd;
// Represent a window reference.
typedef struct clap_window {
const char *api; // one of CLAP_WINDOW_API_XXX
union {
clap_nsview cocoa;
clap_xwnd x11;
clap_hwnd win32;
void *ptr; // for anything defined outside of clap
};
} clap_window_t;
// Information to improve window resizing when initiated by the host or window manager.
typedef struct clap_gui_resize_hints {
bool can_resize_horizontally;
bool can_resize_vertically;
// if both horizontal and vertical resize are available, do we preserve the
// aspect ratio, and if so, what is the width x height aspect ratio to preserve.
// These flags are unused if can_resize_horizontally or vertically are false,
// and ratios are unused if preserve is false.
bool preserve_aspect_ratio;
uint32_t aspect_ratio_width;
uint32_t aspect_ratio_height;
} clap_gui_resize_hints_t;
// Size (width, height) is in pixels; the corresponding windowing system extension is
// responsible for defining if it is physical pixels or logical pixels.
typedef struct clap_plugin_gui {
// Returns true if the requested gui api is supported, either in floating (plugin-created)
// or non-floating (embedded) mode.
// [main-thread]
bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating);
// Returns true if the plugin has a preferred api.
// The host has no obligation to honor the plugin preference, this is just a hint.
// The const char **api variable should be explicitly assigned as a pointer to
// one of the CLAP_WINDOW_API_ constants defined above, not strcopied.
// [main-thread]
bool(CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin,
const char **api,
bool *is_floating);
// Create and allocate all resources necessary for the gui.
//
// If is_floating is true, then the window will not be managed by the host. The plugin
// can set its window to stays above the parent window, see set_transient().
// api may be null or blank for floating window.
//
// If is_floating is false, then the plugin has to embed its window into the parent window, see
// set_parent().
//
// After this call, the GUI may not be visible yet; don't forget to call show().
//
// Returns true if the GUI is successfully created.
// [main-thread]
bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating);
// Free all resources associated with the gui.
// [main-thread]
void(CLAP_ABI *destroy)(const clap_plugin_t *plugin);
// Set the absolute GUI scaling factor, and override any OS info.
// Should not be used if the windowing api relies upon logical pixels.
//
// If the plugin prefers to work out the scaling factor itself by querying the OS directly,
// then ignore the call.
//
// scale = 2 means 200% scaling.
//
// Returns true if the scaling could be applied
// Returns false if the call was ignored, or the scaling could not be applied.
// [main-thread]
bool(CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale);
// Get the current size of the plugin UI.
// clap_plugin_gui->create() must have been called prior to asking the size.
//
// Returns true if the plugin could get the size.
// [main-thread]
bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
// Returns true if the window is resizeable (mouse drag).
// [main-thread & !floating]
bool(CLAP_ABI *can_resize)(const clap_plugin_t *plugin);
// Returns true if the plugin can provide hints on how to resize the window.
// [main-thread & !floating]
bool(CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints);
// If the plugin gui is resizable, then the plugin will calculate the closest
// usable size which fits in the given size.
// This method does not change the size.
//
// Returns true if the plugin could adjust the given size.
// [main-thread & !floating]
bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
// Sets the window size.
//
// Returns true if the plugin could resize its window to the given size.
// [main-thread & !floating]
bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height);
// Embeds the plugin window into the given window.
//
// Returns true on success.
// [main-thread & !floating]
bool(CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window);
// Set the plugin floating window to stay above the given window.
//
// Returns true on success.
// [main-thread & floating]
bool(CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window);
// Suggests a window title. Only for floating windows.
//
// [main-thread & floating]
void(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title);
// Show the window.
//
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *show)(const clap_plugin_t *plugin);
// Hide the window, this method does not free the resources, it just hides
// the window content. Yet it may be a good idea to stop painting timers.
//
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *hide)(const clap_plugin_t *plugin);
} clap_plugin_gui_t;
typedef struct clap_host_gui {
// The host should call get_resize_hints() again.
// [thread-safe & !floating]
void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host);
// Request the host to resize the client area to width, height.
// Return true if the new size is accepted, false otherwise.
// The host doesn't have to call set_size().
//
// Note: if not called from the main thread, then a return value simply means that the host
// acknowledged the request and will process it asynchronously. If the request then can't be
// satisfied then the host will call set_size() to revert the operation.
// [thread-safe & !floating]
bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height);
// Request the host to show the plugin gui.
// Return true on success, false otherwise.
// [thread-safe]
bool(CLAP_ABI *request_show)(const clap_host_t *host);
// Request the host to hide the plugin gui.
// Return true on success, false otherwise.
// [thread-safe]
bool(CLAP_ABI *request_hide)(const clap_host_t *host);
// The floating window has been closed, or the connection to the gui has been lost.
//
// If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge
// the gui destruction.
// [thread-safe]
void(CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed);
} clap_host_gui_t;
#ifdef __cplusplus
}
#endif

27
tests/clap/ext/latency.h Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_latency {
// Returns the plugin latency in samples.
// [main-thread & (being-activated | active)]
uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin);
} clap_plugin_latency_t;
typedef struct clap_host_latency {
// Tell the host that the latency changed.
// The latency is only allowed to change during plugin->activate.
// If the plugin is activated, call host->request_restart()
// [main-thread & being-activated]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_latency_t;
#ifdef __cplusplus
}
#endif

33
tests/clap/ext/log.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_LOG[] = "clap.log";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_LOG_DEBUG = 0,
CLAP_LOG_INFO = 1,
CLAP_LOG_WARNING = 2,
CLAP_LOG_ERROR = 3,
CLAP_LOG_FATAL = 4,
// These severities should be used to report misbehaviour.
// The plugin one can be used by a layer between the plugin and the host.
CLAP_LOG_HOST_MISBEHAVING = 5,
CLAP_LOG_PLUGIN_MISBEHAVING = 6,
};
typedef int32_t clap_log_severity;
typedef struct clap_host_log {
// Log a message through the host.
// [thread-safe]
void(CLAP_ABI *log)(const clap_host_t *host, clap_log_severity severity, const char *msg);
} clap_host_log_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,37 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
#ifdef __cplusplus
extern "C" {
#endif
static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_NAME[] = "clap.note-name";
typedef struct clap_note_name {
char name[CLAP_NAME_SIZE];
int16_t port; // -1 for every port
int16_t key; // -1 for every key
int16_t channel; // -1 for every channel
} clap_note_name_t;
typedef struct clap_plugin_note_name {
// Return the number of note names
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Returns true on success and stores the result into note_name
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin, uint32_t index, clap_note_name_t *note_name);
} clap_plugin_note_name_t;
typedef struct clap_host_note_name {
// Informs the host that the note names have changed.
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_note_name_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,79 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
/// @page Note Ports
///
/// This extension provides a way for the plugin to describe its current note ports.
/// If the plugin does not implement this extension, it won't have note input or output.
/// The plugin is only allowed to change its note ports configuration while it is deactivated.
static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_PORTS[] = "clap.note-ports";
#ifdef __cplusplus
extern "C" {
#endif
enum clap_note_dialect {
// Uses clap_event_note and clap_event_note_expression.
CLAP_NOTE_DIALECT_CLAP = 1 << 0,
// Uses clap_event_midi, no polyphonic expression
CLAP_NOTE_DIALECT_MIDI = 1 << 1,
// Uses clap_event_midi, with polyphonic expression (MPE)
CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2,
// Uses clap_event_midi2
CLAP_NOTE_DIALECT_MIDI2 = 1 << 3,
};
typedef struct clap_note_port_info {
// id identifies a port and must be stable.
// id may overlap between input and output ports.
clap_id id;
uint32_t supported_dialects; // bitfield, see clap_note_dialect
uint32_t preferred_dialect; // one value of clap_note_dialect
char name[CLAP_NAME_SIZE]; // displayable name, i18n?
} clap_note_port_info_t;
// The note ports scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_note_ports {
// Number of ports, for either input or output.
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input);
// Get info about a note port.
// Returns true on success and stores the result into info.
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
uint32_t index,
bool is_input,
clap_note_port_info_t *info);
} clap_plugin_note_ports_t;
enum {
// The ports have changed, the host shall perform a full scan of the ports.
// This flag can only be used if the plugin is not active.
// If the plugin active, call host->request_restart() and then call rescan()
// when the host calls deactivate()
CLAP_NOTE_PORTS_RESCAN_ALL = 1 << 0,
// The ports name did change, the host can scan them right away.
CLAP_NOTE_PORTS_RESCAN_NAMES = 1 << 1,
};
typedef struct clap_host_note_ports {
// Query which dialects the host supports
// [main-thread]
uint32_t(CLAP_ABI *supported_dialects)(const clap_host_t *host);
// Rescan the full list of note ports according to the flags.
// [main-thread]
void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags);
} clap_host_note_ports_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,77 @@
#pragma once
#include "params.h"
#include "../color.h"
// This extension lets the host tell the plugin to display a little color based indication on the
// parameter. This can be used to indicate:
// - a physical controller is mapped to a parameter
// - the parameter is current playing an automation
// - the parameter is overriding the automation
// - etc...
//
// The color semantic depends upon the host here and the goal is to have a consistent experience
// across all plugins.
static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_INDICATION[] = "clap.param-indication/4";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_INDICATION_COMPAT[] = "clap.param-indication.draft/4";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// The host doesn't have an automation for this parameter
CLAP_PARAM_INDICATION_AUTOMATION_NONE = 0,
// The host has an automation for this parameter, but it isn't playing it
CLAP_PARAM_INDICATION_AUTOMATION_PRESENT = 1,
// The host is playing an automation for this parameter
CLAP_PARAM_INDICATION_AUTOMATION_PLAYING = 2,
// The host is recording an automation on this parameter
CLAP_PARAM_INDICATION_AUTOMATION_RECORDING = 3,
// The host should play an automation for this parameter, but the user has started to adjust this
// parameter and is overriding the automation playback
CLAP_PARAM_INDICATION_AUTOMATION_OVERRIDING = 4,
};
typedef struct clap_plugin_param_indication {
// Sets or clears a mapping indication.
//
// has_mapping: does the parameter currently has a mapping?
// color: if set, the color to use to highlight the control in the plugin GUI
// label: if set, a small string to display on top of the knob which identifies the hardware
// controller description: if set, a string which can be used in a tooltip, which describes the
// current mapping
//
// Parameter indications should not be saved in the plugin context, and are off by default.
// [main-thread]
void(CLAP_ABI *set_mapping)(const clap_plugin_t *plugin,
clap_id param_id,
bool has_mapping,
const clap_color_t *color,
const char *label,
const char *description);
// Sets or clears an automation indication.
//
// automation_state: current automation state for the given parameter
// color: if set, the color to use to display the automation indication in the plugin GUI
//
// Parameter indications should not be saved in the plugin context, and are off by default.
// [main-thread]
void(CLAP_ABI *set_automation)(const clap_plugin_t *plugin,
clap_id param_id,
uint32_t automation_state,
const clap_color_t *color);
} clap_plugin_param_indication_t;
#ifdef __cplusplus
}
#endif

382
tests/clap/ext/params.h Normal file
View file

@ -0,0 +1,382 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
/// @page Parameters
/// @brief parameters management
///
/// Main idea:
///
/// The host sees the plugin as an atomic entity; and acts as a controller on top of its parameters.
/// The plugin is responsible for keeping its audio processor and its GUI in sync.
///
/// The host can at any time read parameters' value on the [main-thread] using
/// @ref clap_plugin_params.get_value().
///
/// There are two options to communicate parameter value changes, and they are not concurrent.
/// - send automation points during clap_plugin.process()
/// - send automation points during clap_plugin_params.flush(), for parameter changes
/// without processing audio
///
/// When the plugin changes a parameter value, it must inform the host.
/// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush().
/// If the user is adjusting the value, don't forget to mark the beginning and end
/// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END
/// events.
///
/// @note MIDI CCs are tricky because you may not know when the parameter adjustment ends.
/// Also if the host records incoming MIDI CC and parameter change automation at the same time,
/// there will be a conflict at playback: MIDI CC vs Automation.
/// The parameter automation will always target the same parameter because the param_id is stable.
/// The MIDI CC may have a different mapping in the future and may result in a different playback.
///
/// When a MIDI CC changes a parameter's value, set the flag CLAP_EVENT_DONT_RECORD in
/// clap_event_param.header.flags. That way the host may record the MIDI CC automation, but not the
/// parameter change and there won't be conflict at playback.
///
/// Scenarios:
///
/// I. Loading a preset
/// - load the preset in a temporary state
/// - call @ref clap_host_params.rescan() if anything changed
/// - call @ref clap_host_latency.changed() if latency changed
/// - invalidate any other info that may be cached by the host
/// - if the plugin is activated and the preset will introduce breaking changes
/// (latency, audio ports, new parameters, ...) be sure to wait for the host
/// to deactivate the plugin to apply those changes.
/// If there are no breaking changes, the plugin can apply them them right away.
/// The plugin is responsible for updating both its audio processor and its gui.
///
/// II. Turning a knob on the DAW interface
/// - the host will send an automation event to the plugin via a process() or flush()
///
/// III. Turning a knob on the Plugin interface
/// - the plugin is responsible for sending the parameter value to its audio processor
/// - call clap_host_params->request_flush() or clap_host->request_process().
/// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(),
/// send an automation event and don't forget to wrap the parameter change(s)
/// with CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END to define the
/// beginning and end of the gesture.
///
/// IV. Turning a knob via automation
/// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush().
/// - the plugin is responsible for updating its GUI
///
/// V. Turning a knob via plugin's internal MIDI mapping
/// - the plugin sends a CLAP_EVENT_PARAM_VALUE output event, set should_record to false
/// - the plugin is responsible for updating its GUI
///
/// VI. Adding or removing parameters
/// - if the plugin is activated call clap_host->restart()
/// - once the plugin isn't active:
/// - apply the new state
/// - if a parameter is gone or is created with an id that may have been used before,
/// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL)
/// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL)
///
/// CLAP allows the plugin to change the parameter range, yet the plugin developer
/// should be aware that doing so isn't without risk, especially if you made the
/// promise to never change the sound. If you want to be 100% certain that the
/// sound will not change with all host, then simply never change the range.
///
/// There are two approaches to automations, either you automate the plain value,
/// or you automate the knob position. The first option will be robust to a range
/// increase, while the second won't be.
///
/// If the host goes with the second approach (automating the knob position), it means
/// that the plugin is hosted in a relaxed environment regarding sound changes (they are
/// accepted, and not a concern as long as they are reasonable). Though, stepped parameters
/// should be stored as plain value in the document.
///
/// If the host goes with the first approach, there will still be situation where the
/// sound may inevitably change. For example, if the plugin increase the range, there
/// is an automation playing at the max value and on top of that an LFO is applied.
/// See the following curve:
/// .
/// . .
/// ..... . .
/// before: . . and after: . .
///
/// Persisting parameter values:
///
/// Plugins are responsible for persisting their parameter's values between
/// sessions by implementing the state extension. Otherwise parameter value will
/// not be recalled when reloading a project. Hosts should _not_ try to save and
/// restore parameter values for plugins that don't implement the state
/// extension.
///
/// Advice for the host:
///
/// - store plain values in the document (automation)
/// - store modulation amount in plain value delta, not in percentage
/// - when you apply a CC mapping, remember the min/max plain values so you can adjust
/// - do not implement a parameter saving fall back for plugins that don't
/// implement the state extension
///
/// Advice for the plugin:
///
/// - think carefully about your parameter range when designing your DSP
/// - avoid shrinking parameter ranges, they are very likely to change the sound
/// - consider changing the parameter range as a tradeoff: what you improve vs what you break
/// - make sure to implement saving and loading the parameter values using the
/// state extension
/// - if you plan to use adapters for other plugin formats, then you need to pay extra
/// attention to the adapter requirements
static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// Is this param stepped? (integer values only)
// if so the double value is converted to integer using a cast (equivalent to trunc).
CLAP_PARAM_IS_STEPPED = 1 << 0,
// Useful for periodic parameters like a phase
CLAP_PARAM_IS_PERIODIC = 1 << 1,
// The parameter should not be shown to the user, because it is currently not used.
// It is not necessary to process automation for this parameter.
CLAP_PARAM_IS_HIDDEN = 1 << 2,
// The parameter can't be changed by the host.
CLAP_PARAM_IS_READONLY = 1 << 3,
// This parameter is used to merge the plugin and host bypass button.
// It implies that the parameter is stepped.
// min: 0 -> bypass off
// max: 1 -> bypass on
CLAP_PARAM_IS_BYPASS = 1 << 4,
// When set:
// - automation can be recorded
// - automation can be played back
//
// The host can send live user changes for this parameter regardless of this flag.
//
// If this parameter affects the internal processing structure of the plugin, ie: max delay, fft
// size, ... and the plugins needs to re-allocate its working buffers, then it should call
// host->request_restart(), and perform the change once the plugin is re-activated.
CLAP_PARAM_IS_AUTOMATABLE = 1 << 5,
// Does this parameter support per note automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6,
// Does this parameter support per key automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7,
// Does this parameter support per channel automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8,
// Does this parameter support per port automations?
CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9,
// Does this parameter support the modulation signal?
CLAP_PARAM_IS_MODULATABLE = 1 << 10,
// Does this parameter support per note modulations?
CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11,
// Does this parameter support per key modulations?
CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12,
// Does this parameter support per channel modulations?
CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13,
// Does this parameter support per port modulations?
CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14,
// Any change to this parameter will affect the plugin output and requires to be done via
// process() if the plugin is active.
//
// A simple example would be a DC Offset, changing it will change the output signal and must be
// processed.
CLAP_PARAM_REQUIRES_PROCESS = 1 << 15,
// This parameter represents an enumerated value.
// If you set this flag, then you must set CLAP_PARAM_IS_STEPPED too.
// All values from min to max must not have a blank value_to_text().
CLAP_PARAM_IS_ENUM = 1 << 16,
};
typedef uint32_t clap_param_info_flags;
/* This describes a parameter */
typedef struct clap_param_info {
// Stable parameter identifier, it must never change.
clap_id id;
clap_param_info_flags flags;
// This value is optional and set by the plugin.
// Its purpose is to provide fast access to the plugin parameter object by caching its pointer.
// For instance:
//
// in clap_plugin_params.get_info():
// Parameter *p = findParameter(param_id);
// param_info->cookie = p;
//
// later, in clap_plugin.process():
//
// Parameter *p = (Parameter *)event->cookie;
// if (!p) [[unlikely]]
// p = findParameter(event->param_id);
//
// where findParameter() is a function the plugin implements to map parameter ids to internal
// objects.
//
// Important:
// - The cookie is invalidated by a call to clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or
// when the plugin is destroyed.
// - The host will either provide the cookie as issued or nullptr in events addressing
// parameters.
// - The plugin must gracefully handle the case of a cookie which is nullptr.
// - Many plugins will process the parameter events more quickly if the host can provide the
// cookie in a faster time than a hashmap lookup per param per event.
void *cookie;
// The display name. eg: "Volume". This does not need to be unique. Do not include the module
// text in this. The host should concatenate/format the module + name in the case where showing
// the name alone would be too vague.
char name[CLAP_NAME_SIZE];
// The module path containing the param, eg: "Oscillators/Wavetable 1".
// '/' will be used as a separator to show a tree-like structure.
char module[CLAP_PATH_SIZE];
double min_value; // Minimum plain value. Must be finite (`std::isfinite` true)
double max_value; // Maximum plain value. Must be finite
double default_value; // Default plain value. Must be in [min, max] range.
} clap_param_info_t;
typedef struct clap_plugin_params {
// Returns the number of parameters.
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Copies the parameter's info to param_info.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin,
uint32_t param_index,
clap_param_info_t *param_info);
// Writes the parameter's current value to out_value.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *get_value)(const clap_plugin_t *plugin, clap_id param_id, double *out_value);
// Fills out_buffer with a null-terminated UTF-8 string that represents the parameter at the
// given 'value' argument. eg: "2.3 kHz". The host should always use this to format parameter
// values before displaying it to the user.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *value_to_text)(const clap_plugin_t *plugin,
clap_id param_id,
double value,
char *out_buffer,
uint32_t out_buffer_capacity);
// Converts the null-terminated UTF-8 param_value_text into a double and writes it to out_value.
// The host can use this to convert user input into a parameter value.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *text_to_value)(const clap_plugin_t *plugin,
clap_id param_id,
const char *param_value_text,
double *out_value);
// Flushes a set of parameter changes.
// This method must not be called concurrently to clap_plugin->process().
//
// Note: if the plugin is processing, then the process() call will already achieve the
// parameter update (bi-directional), so a call to flush isn't required, also be aware
// that the plugin may use the sample offset in process(), while this information would be
// lost within flush().
//
// [active ? audio-thread : main-thread]
void(CLAP_ABI *flush)(const clap_plugin_t *plugin,
const clap_input_events_t *in,
const clap_output_events_t *out);
} clap_plugin_params_t;
enum {
// The parameter values did change, eg. after loading a preset.
// The host will scan all the parameters value.
// The host will not record those changes as automation points.
// New values takes effect immediately.
CLAP_PARAM_RESCAN_VALUES = 1 << 0,
// The value to text conversion changed, and the text needs to be rendered again.
CLAP_PARAM_RESCAN_TEXT = 1 << 1,
// The parameter info did change, use this flag for:
// - name change
// - module change
// - is_periodic (flag)
// - is_hidden (flag)
// New info takes effect immediately.
CLAP_PARAM_RESCAN_INFO = 1 << 2,
// Invalidates everything the host knows about parameters.
// It can only be used while the plugin is deactivated.
// If the plugin is activated use clap_host->restart() and delay any change until the host calls
// clap_plugin->deactivate().
//
// You must use this flag if:
// - some parameters were added or removed.
// - some parameters had critical changes:
// - is_per_note (flag)
// - is_per_key (flag)
// - is_per_channel (flag)
// - is_per_port (flag)
// - is_readonly (flag)
// - is_bypass (flag)
// - is_stepped (flag)
// - is_modulatable (flag)
// - min_value
// - max_value
// - cookie
CLAP_PARAM_RESCAN_ALL = 1 << 3,
};
typedef uint32_t clap_param_rescan_flags;
enum {
// Clears all possible references to a parameter
CLAP_PARAM_CLEAR_ALL = 1 << 0,
// Clears all automations to a parameter
CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1,
// Clears all modulations to a parameter
CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2,
};
typedef uint32_t clap_param_clear_flags;
typedef struct clap_host_params {
// Rescan the full list of parameters according to the flags.
// [main-thread]
void(CLAP_ABI *rescan)(const clap_host_t *host, clap_param_rescan_flags flags);
// Clears references to a parameter.
// [main-thread]
void(CLAP_ABI *clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags);
// Request a parameter flush.
//
// The host will then schedule a call to either:
// - clap_plugin.process()
// - clap_plugin_params.flush()
//
// This function is always safe to use and should not be called from an [audio-thread] as the
// plugin would already be within process() or flush().
//
// [thread-safe,!audio-thread]
void(CLAP_ABI *request_flush)(const clap_host_t *host);
} clap_host_params_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,49 @@
#pragma once
#include "../plugin.h"
// This extension let your plugin hook itself into the host select/poll/epoll/kqueue reactor.
// This is useful to handle asynchronous I/O on the main thread.
static CLAP_CONSTEXPR const char CLAP_EXT_POSIX_FD_SUPPORT[] = "clap.posix-fd-support";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// IO events flags, they can be used to form a mask which describes:
// - which events you are interested in (register_fd/modify_fd)
// - which events happened (on_fd)
CLAP_POSIX_FD_READ = 1 << 0,
CLAP_POSIX_FD_WRITE = 1 << 1,
CLAP_POSIX_FD_ERROR = 1 << 2,
};
typedef uint32_t clap_posix_fd_flags_t;
typedef struct clap_plugin_posix_fd_support {
// This callback is "level-triggered".
// It means that a writable fd will continuously produce "on_fd()" events;
// don't forget using modify_fd() to remove the write notification once you're
// done writing.
//
// [main-thread]
void(CLAP_ABI *on_fd)(const clap_plugin_t *plugin, int fd, clap_posix_fd_flags_t flags);
} clap_plugin_posix_fd_support_t;
typedef struct clap_host_posix_fd_support {
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *register_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags);
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *modify_fd)(const clap_host_t *host, int fd, clap_posix_fd_flags_t flags);
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *unregister_fd)(const clap_host_t *host, int fd);
} clap_host_posix_fd_support_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,53 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load/2";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_PRESET_LOAD_COMPAT[] = "clap.preset-load.draft/2";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_preset_load {
// Loads a preset in the plugin native preset file format from a location.
// The preset discovery provider defines the location and load_key to be passed to this function.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *from_location)(const clap_plugin_t *plugin,
uint32_t location_kind,
const char *location,
const char *load_key);
} clap_plugin_preset_load_t;
typedef struct clap_host_preset_load {
// Called if clap_plugin_preset_load.load() failed.
// os_error: the operating system error, if applicable. If not applicable set it to a non-error
// value, eg: 0 on unix and Windows.
//
// [main-thread]
void(CLAP_ABI *on_error)(const clap_host_t *host,
uint32_t location_kind,
const char *location,
const char *load_key,
int32_t os_error,
const char *msg);
// Informs the host that the following preset has been loaded.
// This contributes to keep in sync the host preset browser and plugin preset browser.
// If the preset was loaded from a container file, then the load_key must be set, otherwise it
// must be null.
//
// [main-thread]
void(CLAP_ABI *loaded)(const clap_host_t *host,
uint32_t location_kind,
const char *location,
const char *load_key);
} clap_host_preset_load_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,83 @@
#pragma once
#include "../plugin.h"
#include "../string-sizes.h"
// This extension let the plugin provide a structured way of mapping parameters to an hardware
// controller.
//
// This is done by providing a set of remote control pages organized by section.
// A page contains up to 8 controls, which references parameters using param_id.
//
// |`- [section:main]
// | `- [name:main] performance controls
// |`- [section:osc]
// | |`- [name:osc1] osc1 page
// | |`- [name:osc2] osc2 page
// | |`- [name:osc-sync] osc sync page
// | `- [name:osc-noise] osc noise page
// |`- [section:filter]
// | |`- [name:flt1] filter 1 page
// | `- [name:flt2] filter 2 page
// |`- [section:env]
// | |`- [name:env1] env1 page
// | `- [name:env2] env2 page
// |`- [section:lfo]
// | |`- [name:lfo1] env1 page
// | `- [name:lfo2] env2 page
// `- etc...
//
// One possible workflow is to have a set of buttons, which correspond to a section.
// Pressing that button once gets you to the first page of the section.
// Press it again to cycle through the section's pages.
static CLAP_CONSTEXPR const char CLAP_EXT_REMOTE_CONTROLS[] = "clap.remote-controls/2";
// The latest draft is 100% compatible
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_REMOTE_CONTROLS_COMPAT[] = "clap.remote-controls.draft/2";
#ifdef __cplusplus
extern "C" {
#endif
enum { CLAP_REMOTE_CONTROLS_COUNT = 8 };
typedef struct clap_remote_controls_page {
char section_name[CLAP_NAME_SIZE];
clap_id page_id;
char page_name[CLAP_NAME_SIZE];
clap_id param_ids[CLAP_REMOTE_CONTROLS_COUNT];
// This is used to separate device pages versus preset pages.
// If true, then this page is specific to this preset.
bool is_for_preset;
} clap_remote_controls_page_t;
typedef struct clap_plugin_remote_controls {
// Returns the number of pages.
// [main-thread]
uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Get a page by index.
// Returns true on success and stores the result into page.
// [main-thread]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
uint32_t page_index,
clap_remote_controls_page_t *page);
} clap_plugin_remote_controls_t;
typedef struct clap_host_remote_controls {
// Informs the host that the remote controls have changed.
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
// Suggest a page to the host because it corresponds to what the user is currently editing in the
// plugin's GUI.
// [main-thread]
void(CLAP_ABI *suggest_page)(const clap_host_t *host, clap_id page_id);
} clap_host_remote_controls_t;
#ifdef __cplusplus
}
#endif

39
tests/clap/ext/render.h Normal file
View file

@ -0,0 +1,39 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_RENDER[] = "clap.render";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// Default setting, for "realtime" processing
CLAP_RENDER_REALTIME = 0,
// For processing without realtime pressure
// The plugin may use more expensive algorithms for higher sound quality.
CLAP_RENDER_OFFLINE = 1,
};
typedef int32_t clap_plugin_render_mode;
// The render extension is used to let the plugin know if it has "realtime"
// pressure to process.
//
// If this information does not influence your rendering code, then don't
// implement this extension.
typedef struct clap_plugin_render {
// Returns true if the plugin has a hard requirement to process in real-time.
// This is especially useful for plugin acting as a proxy to an hardware device.
// [main-thread]
bool(CLAP_ABI *has_hard_realtime_requirement)(const clap_plugin_t *plugin);
// Returns true if the rendering mode could be applied.
// [main-thread]
bool(CLAP_ABI *set)(const clap_plugin_t *plugin, clap_plugin_render_mode mode);
} clap_plugin_render_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,72 @@
#pragma once
#include "../plugin.h"
#include "../stream.h"
/// @page state-context extension
/// @brief extended state handling
///
/// This extension lets the host save and load the plugin state with different semantics depending
/// on the context.
///
/// Briefly, when loading a preset or duplicating a device, the plugin may want to partially load
/// the state and initialize certain things differently, like handling limited resources or fixed
/// connections to external hardware resources.
///
/// Save and Load operations may have a different context.
/// All three operations should be equivalent:
/// 1. clap_plugin_state_context.load(clap_plugin_state.save(), CLAP_STATE_CONTEXT_FOR_PRESET)
/// 2. clap_plugin_state.load(clap_plugin_state_context.save(CLAP_STATE_CONTEXT_FOR_PRESET))
/// 3. clap_plugin_state_context.load(
/// clap_plugin_state_context.save(CLAP_STATE_CONTEXT_FOR_PRESET),
/// CLAP_STATE_CONTEXT_FOR_PRESET)
///
/// If in doubt, fallback to clap_plugin_state.
///
/// If the plugin implements CLAP_EXT_STATE_CONTEXT then it is mandatory to also implement
/// CLAP_EXT_STATE.
///
/// It is unspecified which context is equivalent to clap_plugin_state.{save,load}()
#ifdef __cplusplus
extern "C" {
#endif
static CLAP_CONSTEXPR const char CLAP_EXT_STATE_CONTEXT[] = "clap.state-context/2";
enum clap_plugin_state_context_type {
// suitable for storing and loading a state as a preset
CLAP_STATE_CONTEXT_FOR_PRESET = 1,
// suitable for duplicating a plugin instance
CLAP_STATE_CONTEXT_FOR_DUPLICATE = 2,
// suitable for storing and loading a state within a project/song
CLAP_STATE_CONTEXT_FOR_PROJECT = 3,
};
typedef struct clap_plugin_state_context {
// Saves the plugin state into stream, according to context_type.
// Returns true if the state was correctly saved.
//
// Note that the result may be loaded by both clap_plugin_state.load() and
// clap_plugin_state_context.load().
// [main-thread]
bool(CLAP_ABI *save)(const clap_plugin_t *plugin,
const clap_ostream_t *stream,
uint32_t context_type);
// Loads the plugin state from stream, according to context_type.
// Returns true if the state was correctly restored.
//
// Note that the state may have been saved by clap_plugin_state.save() or
// clap_plugin_state_context.save() with a different context_type.
// [main-thread]
bool(CLAP_ABI *load)(const clap_plugin_t *plugin,
const clap_istream_t *stream,
uint32_t context_type);
} clap_plugin_state_context_t;
#ifdef __cplusplus
}
#endif

45
tests/clap/ext/state.h Normal file
View file

@ -0,0 +1,45 @@
#pragma once
#include "../plugin.h"
#include "../stream.h"
/// @page State
/// @brief state management
///
/// Plugins can implement this extension to save and restore both parameter
/// values and non-parameter state. This is used to persist a plugin's state
/// between project reloads, when duplicating and copying plugin instances, and
/// for host-side preset management.
///
/// If you need to know if the save/load operation is meant for duplicating a plugin
/// instance, for saving/loading a plugin preset or while saving/loading the project
/// then consider implementing CLAP_EXT_STATE_CONTEXT in addition to CLAP_EXT_STATE.
static CLAP_CONSTEXPR const char CLAP_EXT_STATE[] = "clap.state";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_state {
// Saves the plugin state into stream.
// Returns true if the state was correctly saved.
// [main-thread]
bool(CLAP_ABI *save)(const clap_plugin_t *plugin, const clap_ostream_t *stream);
// Loads the plugin state from stream.
// Returns true if the state was correctly restored.
// [main-thread]
bool(CLAP_ABI *load)(const clap_plugin_t *plugin, const clap_istream_t *stream);
} clap_plugin_state_t;
typedef struct clap_host_state {
// Tell the host that the plugin state has changed and should be saved again.
// If a parameter value changes, then it is implicit that the state is dirty.
// [main-thread]
void(CLAP_ABI *mark_dirty)(const clap_host_t *host);
} clap_host_state_t;
#ifdef __cplusplus
}
#endif

89
tests/clap/ext/surround.h Normal file
View file

@ -0,0 +1,89 @@
#pragma once
#include "../plugin.h"
// This extension can be used to specify the channel mapping used by the plugin.
//
// To have consistent surround features across all the plugin instances,
// here is the proposed workflow:
// 1. the plugin queries the host preferred channel mapping and
// adjusts its configuration to match it.
// 2. the host checks how the plugin is effectively configured and honors it.
//
// If the host decides to change the project's surround setup:
// 1. deactivate the plugin
// 2. host calls clap_plugin_surround->changed()
// 3. plugin calls clap_host_surround->get_preferred_channel_map()
// 4. plugin eventually calls clap_host_surround->changed()
// 5. host calls clap_plugin_surround->get_channel_map() if changed
// 6. host activates the plugin and can start processing audio
//
// If the plugin wants to change its surround setup:
// 1. call host->request_restart() if the plugin is active
// 2. once deactivated plugin calls clap_host_surround->changed()
// 3. host calls clap_plugin_surround->get_channel_map()
// 4. host activates the plugin and can start processing audio
static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND[] = "clap.surround/4";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND_COMPAT[] = "clap.surround.draft/4";
static CLAP_CONSTEXPR const char CLAP_PORT_SURROUND[] = "surround";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_SURROUND_FL = 0, // Front Left
CLAP_SURROUND_FR = 1, // Front Right
CLAP_SURROUND_FC = 2, // Front Center
CLAP_SURROUND_LFE = 3, // Low Frequency
CLAP_SURROUND_BL = 4, // Back (Rear) Left
CLAP_SURROUND_BR = 5, // Back (Rear) Right
CLAP_SURROUND_FLC = 6, // Front Left of Center
CLAP_SURROUND_FRC = 7, // Front Right of Center
CLAP_SURROUND_BC = 8, // Back (Rear) Center
CLAP_SURROUND_SL = 9, // Side Left
CLAP_SURROUND_SR = 10, // Side Right
CLAP_SURROUND_TC = 11, // Top (Height) Center
CLAP_SURROUND_TFL = 12, // Top (Height) Front Left
CLAP_SURROUND_TFC = 13, // Top (Height) Front Center
CLAP_SURROUND_TFR = 14, // Top (Height) Front Right
CLAP_SURROUND_TBL = 15, // Top (Height) Back (Rear) Left
CLAP_SURROUND_TBC = 16, // Top (Height) Back (Rear) Center
CLAP_SURROUND_TBR = 17, // Top (Height) Back (Rear) Right
CLAP_SURROUND_TSL = 18, // Top (Height) Side Left
CLAP_SURROUND_TSR = 19, // Top (Height) Side Right
};
typedef struct clap_plugin_surround {
// Checks if a given channel mask is supported.
// The channel mask is a bitmask, for example:
// (1 << CLAP_SURROUND_FL) | (1 << CLAP_SURROUND_FR) | ...
// [main-thread]
bool(CLAP_ABI *is_channel_mask_supported)(const clap_plugin_t *plugin, uint64_t channel_mask);
// Stores the surround identifier of each channel into the channel_map array.
// Returns the number of elements stored in channel_map.
// channel_map_capacity must be greater or equal to the channel count of the given port.
// [main-thread]
uint32_t(CLAP_ABI *get_channel_map)(const clap_plugin_t *plugin,
bool is_input,
uint32_t port_index,
uint8_t *channel_map,
uint32_t channel_map_capacity);
} clap_plugin_surround_t;
typedef struct clap_host_surround {
// Informs the host that the channel map has changed.
// The channel map can only change when the plugin is de-activated.
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_surround_t;
#ifdef __cplusplus
}
#endif

26
tests/clap/ext/tail.h Normal file
View file

@ -0,0 +1,26 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TAIL[] = "clap.tail";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_tail {
// Returns tail length in samples.
// Any value greater or equal to INT32_MAX implies infinite tail.
// [main-thread,audio-thread]
uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin);
} clap_plugin_tail_t;
typedef struct clap_host_tail {
// Tell the host that the tail has changed.
// [audio-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_tail_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,72 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_CHECK[] = "clap.thread-check";
#ifdef __cplusplus
extern "C" {
#endif
/// @page thread-check
///
/// CLAP defines two symbolic threads:
///
/// main-thread:
/// This is the thread in which most of the interaction between the plugin and host happens.
/// This will be the same OS thread throughout the lifetime of the plug-in.
/// On macOS and Windows, this must be the thread on which gui and timer events are received
/// (i.e., the main thread of the program).
/// It isn't a realtime thread, yet this thread needs to respond fast enough to allow responsive
/// user interaction, so it is strongly recommended plugins run long,and expensive or blocking
/// tasks such as preset indexing or asset loading in dedicated background threads started by the
/// plugin.
///
/// audio-thread:
/// This thread can be used for realtime audio processing. Its execution should be as
/// deterministic as possible to meet the audio interface's deadline (can be <1ms). There are a
/// known set of operations that should be avoided: malloc() and free(), contended locks and
/// mutexes, I/O, waiting, and so forth.
///
/// The audio-thread is symbolic, there isn't one OS thread that remains the
/// audio-thread for the plugin lifetime. A host is may opt to have a
/// thread pool and the plugin.process() call may be scheduled on different OS threads over time.
/// However, the host must guarantee that single plugin instance will not be two audio-threads
/// at the same time.
///
/// Functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread,
/// including the main-thread as the audio-thread, as long as it can guarantee that only one OS
/// thread is the audio-thread at a time in a plugin instance. The audio-thread can be seen as a
/// concurrency guard for all functions marked with [audio-thread].
///
/// The real-time constraint on the [audio-thread] interacts closely with the render extension.
/// If a plugin doesn't implement render, then that plugin must have all [audio-thread] functions
/// meet the real time standard. If the plugin does implement render, and returns true when
/// render mode is set to real-time or if the plugin advertises a hard realtime requirement, it
/// must implement realtime constraints. Hosts also provide functions marked [audio-thread].
/// These can be safely called by a plugin in the audio thread. Therefore hosts must either (1)
/// implement those functions meeting the real-time constraints or (2) not process plugins which
/// advertise a hard realtime constraint or don't implement the render extension. Hosts which
/// provide [audio-thread] functions outside these conditions may experience inconsistent or
/// inaccurate rendering.
///
/// Clap also tags some functions as [thread-safe]. Functions tagged as [thread-safe] can be called
/// from any thread unless explicitly counter-indicated (for instance [thread-safe, !audio-thread])
/// and may be called concurrently.
// This interface is useful to do runtime checks and make
// sure that the functions are called on the correct threads.
// It is highly recommended that hosts implement this extension.
typedef struct clap_host_thread_check {
// Returns true if "this" thread is the main thread.
// [thread-safe]
bool(CLAP_ABI *is_main_thread)(const clap_host_t *host);
// Returns true if "this" thread is one of the audio threads.
// [thread-safe]
bool(CLAP_ABI *is_audio_thread)(const clap_host_t *host);
} clap_host_thread_check_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,66 @@
#pragma once
#include "../plugin.h"
/// @page
///
/// This extension lets the plugin use the host's thread pool.
///
/// The plugin must provide @ref clap_plugin_thread_pool, and the host may provide @ref
/// clap_host_thread_pool. If it doesn't, the plugin should process its data by its own means. In
/// the worst case, a single threaded for-loop.
///
/// Simple example with N voices to process
///
/// @code
/// void myplug_thread_pool_exec(const clap_plugin *plugin, uint32_t voice_index)
/// {
/// compute_voice(plugin, voice_index);
/// }
///
/// void myplug_process(const clap_plugin *plugin, const clap_process *process)
/// {
/// ...
/// bool didComputeVoices = false;
/// if (host_thread_pool && host_thread_pool.exec)
/// didComputeVoices = host_thread_pool.request_exec(host, plugin, N);
///
/// if (!didComputeVoices)
/// for (uint32_t i = 0; i < N; ++i)
/// myplug_thread_pool_exec(plugin, i);
/// ...
/// }
/// @endcode
///
/// Be aware that using a thread pool may break hard real-time rules due to the thread
/// synchronization involved.
///
/// If the host knows that it is running under hard real-time pressure it may decide to not
/// provide this interface.
static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_POOL[] = "clap.thread-pool";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_thread_pool {
// Called by the thread pool
void(CLAP_ABI *exec)(const clap_plugin_t *plugin, uint32_t task_index);
} clap_plugin_thread_pool_t;
typedef struct clap_host_thread_pool {
// Schedule num_tasks jobs in the host thread pool.
// It can't be called concurrently or from the thread pool.
// Will block until all the tasks are processed.
// This must be used exclusively for realtime processing within the process call.
// Returns true if the host did execute all the tasks, false if it rejected the request.
// The host should check that the plugin is within the process call, and if not, reject the exec
// request.
// [audio-thread]
bool(CLAP_ABI *request_exec)(const clap_host_t *host, uint32_t num_tasks);
} clap_host_thread_pool_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,31 @@
#pragma once
#include "../plugin.h"
static CLAP_CONSTEXPR const char CLAP_EXT_TIMER_SUPPORT[] = "clap.timer-support";
#ifdef __cplusplus
extern "C" {
#endif
typedef struct clap_plugin_timer_support {
// [main-thread]
void(CLAP_ABI *on_timer)(const clap_plugin_t *plugin, clap_id timer_id);
} clap_plugin_timer_support_t;
typedef struct clap_host_timer_support {
// Registers a periodic timer.
// The host may adjust the period if it is under a certain threshold.
// 30 Hz should be allowed.
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id);
// Returns true on success.
// [main-thread]
bool(CLAP_ABI *unregister_timer)(const clap_host_t *host, clap_id timer_id);
} clap_host_timer_support_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,66 @@
#pragma once
#include "../plugin.h"
#include "../color.h"
#include "../string-sizes.h"
// This extension let the plugin query info about the track it's in.
// It is useful when the plugin is created, to initialize some parameters (mix, dry, wet)
// and pick a suitable configuration regarding audio port type and channel count.
static CLAP_CONSTEXPR const char CLAP_EXT_TRACK_INFO[] = "clap.track-info/1";
// The latest draft is 100% compatible.
// This compat ID may be removed in 2026.
static CLAP_CONSTEXPR const char CLAP_EXT_TRACK_INFO_COMPAT[] = "clap.track-info.draft/1";
#ifdef __cplusplus
extern "C" {
#endif
enum {
CLAP_TRACK_INFO_HAS_TRACK_NAME = (1 << 0),
CLAP_TRACK_INFO_HAS_TRACK_COLOR = (1 << 1),
CLAP_TRACK_INFO_HAS_AUDIO_CHANNEL = (1 << 2),
// This plugin is on a return track, initialize with wet 100%
CLAP_TRACK_INFO_IS_FOR_RETURN_TRACK = (1 << 3),
// This plugin is on a bus track, initialize with appropriate settings for bus processing
CLAP_TRACK_INFO_IS_FOR_BUS = (1 << 4),
// This plugin is on the master, initialize with appropriate settings for channel processing
CLAP_TRACK_INFO_IS_FOR_MASTER = (1 << 5),
};
typedef struct clap_track_info {
uint64_t flags; // see the flags above
// track name, available if flags contain CLAP_TRACK_INFO_HAS_TRACK_NAME
char name[CLAP_NAME_SIZE];
// track color, available if flags contain CLAP_TRACK_INFO_HAS_TRACK_COLOR
clap_color_t color;
// available if flags contain CLAP_TRACK_INFO_HAS_AUDIO_CHANNEL
// see audio-ports.h, struct clap_audio_port_info to learn how to use channel count and port type
int32_t audio_channel_count;
const char *audio_port_type;
} clap_track_info_t;
typedef struct clap_plugin_track_info {
// Called when the info changes.
// [main-thread]
void(CLAP_ABI *changed)(const clap_plugin_t *plugin);
} clap_plugin_track_info_t;
typedef struct clap_host_track_info {
// Get info about the track the plugin belongs to.
// Returns true on success and stores the result into info.
// [main-thread]
bool(CLAP_ABI *get)(const clap_host_t *host, clap_track_info_t *info);
} clap_host_track_info_t;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,56 @@
#pragma once
#include "../plugin.h"
// This extension indicates the number of voices the synthesizer has.
// It is useful for the host when performing polyphonic modulations,
// because the host needs its own voice management and should try to follow
// what the plugin is doing:
// - make the host's voice pool coherent with what the plugin has
// - turn the host's voice management to mono when the plugin is mono
static CLAP_CONSTEXPR const char CLAP_EXT_VOICE_INFO[] = "clap.voice-info";
#ifdef __cplusplus
extern "C" {
#endif
enum {
// Allows the host to send overlapping NOTE_ON events.
// The plugin will then rely upon the note_id to distinguish between them.
CLAP_VOICE_INFO_SUPPORTS_OVERLAPPING_NOTES = 1 << 0,
};
typedef struct clap_voice_info {
// voice_count is the current number of voices that the patch can use
// voice_capacity is the number of voices allocated voices
// voice_count should not be confused with the number of active voices.
//
// 1 <= voice_count <= voice_capacity
//
// For example, a synth can have a capacity of 8 voices, but be configured
// to only use 4 voices: {count: 4, capacity: 8}.
//
// If the voice_count is 1, then the synth is working in mono and the host
// can decide to only use global modulation mapping.
uint32_t voice_count;
uint32_t voice_capacity;
uint64_t flags;
} clap_voice_info_t;
typedef struct clap_plugin_voice_info {
// gets the voice info, returns true on success
// [main-thread && active]
bool(CLAP_ABI *get)(const clap_plugin_t *plugin, clap_voice_info_t *info);
} clap_plugin_voice_info_t;
typedef struct clap_host_voice_info {
// informs the host that the voice info has changed
// [main-thread]
void(CLAP_ABI *changed)(const clap_host_t *host);
} clap_host_voice_info_t;
#ifdef __cplusplus
}
#endif