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:
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)