clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

commit 5aae329e944fb6c854e01d98d60a49713c5f3db2
parent f4deb931f1ed7efe3c4a9ec232f55f675c4a46c5
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Mon, 12 Dec 2022 11:45:19 +0100

Merge branch 'next' into channel-info

Diffstat:
MCMakeLists.txt | 2+-
MREADME.md | 4++++
Minclude/clap/clap.h | 1+
Minclude/clap/events.h | 18++++++++++++++++++
Ainclude/clap/ext/draft/context-menu.h | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/clap/ext/draft/triggers.h | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/clap/ext/params.h | 6++++--
7 files changed, 262 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -10,7 +10,7 @@ set(CLAP_VERSION_MINOR ${CMAKE_MATCH_1}) string(REGEX MATCH "CLAP_VERSION_REVISION \\(\\(uint32_t\\)([0-9]+)\\)" _ ${clap_version_header}) set(CLAP_VERSION_REVISION ${CMAKE_MATCH_1}) -message("CLAP version: ${CLAP_VERSION_MAJOR}.${CLAP_VERSION_MINOR}.${CLAP_VERSION_REVISION}") +message(STATUS "CLAP version: ${CLAP_VERSION_MAJOR}.${CLAP_VERSION_MINOR}.${CLAP_VERSION_REVISION}") project(CLAP LANGUAGES C CXX VERSION ${CLAP_VERSION_MAJOR}.${CLAP_VERSION_MINOR}.${CLAP_VERSION_REVISION}) diff --git a/README.md b/README.md @@ -103,6 +103,10 @@ and use to get a basic plugin experience: - [surround](include/clap/ext/draft/surround.h), inspect surround channel mapping - [ambisonic](include/clap/ext/draft/ambisonic.h), inspect ambisonic channel mapping +## Third-party extensions + +- [`cockos.reaper_extension`](https://github.com/justinfrankel/reaper-sdk/blob/main/reaper-plugins/reaper_plugin.h#L138), access the [REAPER](http://reaper.fm) API + # Adapters - [clap-wrapper](https://github.com/free-audio/clap-wrapper), wrappers for using CLAP in other plugin environments diff --git a/include/clap/clap.h b/include/clap/clap.h @@ -62,3 +62,4 @@ #include "ext/draft/track-info.h" #include "ext/draft/tuning.h" #include "ext/draft/param-indication.h" +#include "ext/draft/context-menu.h" diff --git a/include/clap/events.h b/include/clap/events.h @@ -113,6 +113,10 @@ enum { CLAP_EVENT_MIDI, // raw midi event; clap_event_midi CLAP_EVENT_MIDI_SYSEX, // raw midi sysex event; clap_event_midi_sysex CLAP_EVENT_MIDI2, // raw midi 2 event; clap_event_midi2 + + // Represents a trigger. + // Uses clap_event_trigger. + CLAP_EVENT_TRIGGER, }; // Note on, off, end and choke events. @@ -259,6 +263,20 @@ typedef struct clap_event_midi2 { uint32_t data[4]; } clap_event_midi2_t; +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; + // Input event list, events must be sorted by time. typedef struct clap_input_events { void *ctx; // reserved pointer for the list diff --git a/include/clap/ext/draft/context-menu.h b/include/clap/ext/draft/context-menu.h @@ -0,0 +1,121 @@ +#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.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; + +// Flags for the context menu accelerator +enum { + CLAP_CONTEXT_MENU_ACCELERATOR_MODIFIER_SHIFT = (1 << 0), + CLAP_CONTEXT_MENU_ACCELERATOR_MODIFIER_CONTROL = (1 << 1), + CLAP_CONTEXT_MENU_ACCELERATOR_MODIFIER_ALT = (1 << 2), + + // Windows key or Command key + CLAP_CONTEXT_MENU_ACCELERATOR_MODIFIER_META1 = (1 << 3), +}; + +// Describes a single key strike with its modifiers +typedef struct clap_context_menu_accelerator_key { + uint32_t flags; + uint32_t key; // ASCII key +} clap_context_menu_accelerator_key_t; + +// Describes an accelerator which can consist of a key strike combo +typedef struct clap_context_menu_accelerator { + uint32_t combo_size; + clap_context_menu_accelerator_key_t keys[4]; +} clap_context_menu_accelerator_t; + +// Context menu builder +typedef struct clap_context_menu_builder { + void *ctx; + + // accelerator may be null + bool(CLAP_ABI *add_entry)(const struct clap_context_menu_builder *builder, + const char *label, + const clap_context_menu_accelerator_t *accelerator, + bool is_enabled, + clap_id action_id); + + // accelerator may be null + bool(CLAP_ABI *add_checkmark)(const struct clap_context_menu_builder *builder, + const char *label, + const clap_context_menu_accelerator_t *accelerator, + bool is_enabled, + bool is_checked, + clap_id action_id); + + bool(CLAP_ABI *add_separator)(const struct clap_context_menu_builder *builder); + + // Each begin_submenu() must have a corresponding end_submenu() + bool(CLAP_ABI *begin_submenu)(const struct clap_context_menu_builder *builder, + const char *label); + + bool(CLAP_ABI *end_submenu)(const struct clap_context_menu_builder *builder); +} clap_context_menu_builder_t; + +typedef struct clap_plugin_context_menu { + // If target is null, assume global context + // [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); + + // If target is null, assume global context + // [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 { + // If target is null, assume global context + // [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); + + // If target is null, assume global context + // [main-thread] + bool(CLAP_ABI *perform)(const clap_host_t *host, + const clap_context_menu_target_t *target, + clap_id action_id); + + // [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 + // [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 diff --git a/include/clap/ext/draft/triggers.h b/include/clap/ext/draft/triggers.h @@ -0,0 +1,113 @@ +#pragma once + +#include "../../plugin.h" +#include "../string-sizes.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TRIGGERS[] = "clap.triggers.draft/0"; + +#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: +/// - start recording into a plugin-internal audio/note buffer +/// - trigger a retrospective audio/note looper +/// - trigger a sample-and-hold unit (maybe even per-voice) +/// - trigger an envelope during voice lifetime + +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; + +/* 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. + // 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 diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h @@ -107,7 +107,7 @@ enum { // // The host can send live user changes for this parameter regardless of this flag. // - // If this parameters affect the internal processing structure of the plugin, ie: max delay, fft + // 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, @@ -231,7 +231,7 @@ typedef struct clap_plugin_params { // 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-directionnal), so a call to flush isn't required, also be aware + // 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(). // @@ -268,7 +268,9 @@ enum { // - 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)