commit fc4ba16a4ebcf5d18bbee9efb69a369c854e081f
parent 2b31ad43c20466ab9bd7e91f4ec86771b50c120c
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date: Wed, 5 Jan 2022 10:34:09 +0100
Merge branch 'next'
Diffstat:
17 files changed, 363 insertions(+), 208 deletions(-)
diff --git a/include/clap/chmap.h b/include/clap/chmap.h
@@ -16,11 +16,8 @@ enum {
// see clap_plugin_surround to inspect the exact channel layout
CLAP_CHMAP_SURROUND = 3,
- // FuMa channel ordering
- CLAP_CHMAP_AMBISONIC_FUMA = 4,
-
- // ACN channel ordering
- CLAP_CHMAP_AMBISONIC_ACN = 5,
+ // see clap_plugin_ambisonic to inspect the mapping
+ CLAP_CHMAP_AMBISONIC = 4,
};
typedef int32_t clap_chmap;
diff --git a/include/clap/clap.h b/include/clap/clap.h
@@ -2,7 +2,7 @@
* CLAP - CLever Audio Plugin
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
*
- * Copyright (c) 2014...2021 Alexandre BIQUE <bique.alexandre@gmail.com>
+ * Copyright (c) 2014...2022 Alexandre BIQUE <bique.alexandre@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -46,11 +46,12 @@
#include "ext/latency.h"
#include "ext/thread-check.h"
#include "ext/timer-support.h"
-#include "ext/fd-support.h"
+#include "ext/posix-fd-support.h"
#include "ext/note-name.h"
#include "ext/note-ports.h"
#include "ext/event-filter.h"
#include "ext/thread-pool.h"
+#include "ext/event-registry.h"
#include "ext/draft/preset-load.h"
#include "ext/draft/quick-controls.h"
diff --git a/include/clap/color.h b/include/clap/color.h
@@ -9,10 +9,10 @@ extern "C" {
#pragma pack(push, 1)
typedef struct clap_color {
+ uint8_t alpha;
uint8_t red;
uint8_t green;
uint8_t blue;
- uint8_t alpha;
} clap_color_t;
#pragma pack(pop)
diff --git a/include/clap/entry.h b/include/clap/entry.h
@@ -13,6 +13,18 @@ extern "C" {
// This interface is the entry point of the dynamic library.
//
+// CLAP plugins standard search path:
+//
+// Linux
+// - /usr/lib/clap/
+// - To Be Defined: ~/.clap or ~/.local/lib/clap/ for user location
+//
+// Windows
+// - %CommonFilesFolder%/CLAP/
+//
+// MacOS
+// - /Library/Audio/Plug-Ins/CLAP
+//
// Every methods must be thread-safe.
typedef struct clap_plugin_entry {
clap_version_t clap_version; // initialized to CLAP_VERSION
diff --git a/include/clap/events.h b/include/clap/events.h
@@ -12,18 +12,80 @@ extern "C" {
#pragma pack(push, CLAP_ALIGN)
+// event header
+// must be the first attribute of the event
+typedef struct clap_event_header {
+ alignas(4) uint32_t size; // event size including this header, eg: sizeof (clap_event_note)
+ alignas(4) uint32_t time; // time at which the event happens
+ alignas(2) uint16_t space_id; // event space, see clap_host_event_registry
+ alignas(2) uint16_t type; // event type
+ alignas(4) uint32_t flags; // see clap_event_flags
+} clap_event_header_t;
+
+// The clap core event space
+static const CLAP_CONSTEXPR uint16_t CLAP_CORE_EVENT_SPACE_ID = 0;
+
+enum clap_event_flags {
+ // indicate a live momentary event
+ CLAP_EVENT_IS_LIVE = 1 << 0,
+
+ // live user adjustment begun
+ CLAP_EVENT_BEGIN_ADJUST = 1 << 1,
+
+ // live user adjustment ended
+ CLAP_EVENT_END_ADJUST = 1 << 2,
+
+ // should record this event be recorded?
+ CLAP_EVENT_SHOULD_RECORD = 1 << 3,
+};
+
+// Some of the following events overlap, a note on can be expressed with:
+// - CLAP_EVENT_NOTE_ON
+// - CLAP_EVENT_MIDI
+// - CLAP_EVENT_MIDI2
+//
+// The preferred way of sending a note event is to use CLAP_EVENT_NOTE_*.
+//
+// The same event must not be sent twice: it is forbidden to send a the same note on
+// encoded with both CLAP_EVENT_NOTE_ON and CLAP_EVENT_MIDI.
+//
+// The plugins are encouraged to be able to handle note events encoded as raw midi or midi2,
+// or implement clap_plugin_event_filter and reject raw midi and midi2 events.
enum {
- CLAP_EVENT_NOTE_ON, // press a key; note attribute
- CLAP_EVENT_NOTE_OFF, // release a key; note attribute
- CLAP_EVENT_NOTE_END, // playback of a note is terminated (sent by the plugin); note attribute
- CLAP_EVENT_NOTE_CHOKE, // chokes a set of notes; note attribute
- CLAP_EVENT_NOTE_EXPRESSION, // plays standard note expression; note_expression attribute
- CLAP_EVENT_NOTE_MASK, // current chord/scale; note_mask attribute
- CLAP_EVENT_PARAM_VALUE, // sets a parameter value; param_value attribute
- CLAP_EVENT_PARAM_MOD, // sets a parameter modulation; param_mod attribute
- CLAP_EVENT_TRANSPORT, // update the transport info; transport attribute
- CLAP_EVENT_MIDI, // raw midi event; midi attribute
- CLAP_EVENT_MIDI_SYSEX, // raw midi sysex event; midi_sysex attribute
+ // NOTE_ON and NOTE_OFF represents a key pressed and key released event.
+ //
+ // NOTE_CHOKE is meant to choke the voice(s), like in a drum machine when a closed hihat
+ // chokes an open hihat.
+ //
+ // NOTE_END is sent by the plugin to the host, when a voice terminates.
+ // When using polyphonic modulations, the host has to start voices for its modulators.
+ // This message helps the host to track the plugin's voice management.
+ //
+ // Those four events use the note attribute.
+ CLAP_EVENT_NOTE_ON,
+ CLAP_EVENT_NOTE_OFF,
+ CLAP_EVENT_NOTE_CHOKE,
+ CLAP_EVENT_NOTE_END,
+
+ // Represents a note expression.
+ // Uses the note_expression attribute.
+ CLAP_EVENT_NOTE_EXPRESSION,
+
+ // PARAM_VALUE sets the parameter's value; uses param_value attribute
+ // PARAM_MOD sets the parameter's modulation amount; uses param_mod attribute
+ //
+ // The value heard is: param_value + param_mod.
+ //
+ // In case of a concurrent global value/modulation versus a polyphonic one,
+ // the voice should only use the polyphonic one and the polyphonic modulation
+ // amount will already include the monophonic signal.
+ CLAP_EVENT_PARAM_VALUE,
+ CLAP_EVENT_PARAM_MOD,
+
+ CLAP_EVENT_TRANSPORT, // update the transport info; transport attribute
+ CLAP_EVENT_MIDI, // raw midi event; midi attribute
+ CLAP_EVENT_MIDI_SYSEX, // raw midi sysex event; midi_sysex attribute
+ CLAP_EVENT_MIDI2, // raw midi 2 event; midi2 attribute
};
typedef int32_t clap_event_type;
@@ -34,10 +96,12 @@ typedef int32_t clap_event_type;
* - key and channel are used to match active notes, a value of -1 matches all.
*/
typedef struct clap_event_note {
- int32_t port_index;
- int32_t key; // 0..127
- int32_t channel; // 0..15
- double velocity; // 0..1
+ alignas(4) clap_event_header_t header;
+
+ alignas(2) int16_t port_index;
+ alignas(2) int16_t key; // 0..127
+ alignas(2) int16_t channel; // 0..15
+ alignas(8) double velocity; // 0..1
} clap_event_note_t;
enum {
@@ -62,57 +126,49 @@ enum {
typedef int32_t clap_note_expression;
typedef struct clap_event_note_expression {
+ alignas(4) clap_event_header_t header;
+
alignas(4) clap_note_expression expression_id;
// target a specific port, key and channel, -1 for global
- alignas(4) int32_t port_index;
- alignas(4) int32_t key;
- alignas(4) int32_t channel;
+ alignas(2) int16_t port_index;
+ alignas(2) int16_t key;
+ alignas(2) int16_t channel;
alignas(8) double value; // see expression for the range
} clap_event_note_expression_t;
-enum {
- // live user adjustment begun
- CLAP_EVENT_PARAM_BEGIN_ADJUST = 1 << 0,
-
- // live user adjustment ended
- CLAP_EVENT_PARAM_END_ADJUST = 1 << 1,
-
- // should record this parameter change and create an automation point?
- CLAP_EVENT_PARAM_SHOULD_RECORD = 1 << 2,
-};
-typedef int32_t clap_event_param_flags;
-
typedef struct clap_event_param_value {
+ alignas(4) clap_event_header_t header;
+
// target parameter
void *cookie; // @ref clap_param_info.cookie
alignas(4) clap_id param_id; // @ref clap_param_info.id
// target a specific port, key and channel, -1 for global
- alignas(4) int32_t port_index;
- alignas(4) int32_t key;
- alignas(4) int32_t channel;
-
- alignas(4) clap_event_param_flags flags;
+ alignas(2) int16_t port_index;
+ alignas(2) int16_t key;
+ alignas(2) int16_t channel;
alignas(8) double value;
} clap_event_param_value_t;
typedef struct clap_event_param_mod {
+ alignas(4) clap_event_header_t header;
+
// target parameter
- void *cookie; // @ref clap_param_info.cookie
alignas(4) clap_id param_id; // @ref clap_param_info.id
+ void *cookie; // @ref clap_param_info.cookie
// target a specific port, key and channel, -1 for global
- alignas(4) int32_t port_index;
- alignas(4) int32_t key;
- alignas(4) int32_t channel;
+ alignas(2) int16_t port_index;
+ alignas(2) int16_t key;
+ alignas(2) int16_t channel;
alignas(8) double amount; // modulation amount
} clap_event_param_mod_t;
-enum {
+enum clap_transport_flags {
CLAP_TRANSPORT_HAS_TEMPO = 1 << 0,
CLAP_TRANSPORT_HAS_BEATS_TIMELINE = 1 << 1,
CLAP_TRANSPORT_HAS_SECONDS_TIMELINE = 1 << 2,
@@ -122,10 +178,11 @@ enum {
CLAP_TRANSPORT_IS_LOOP_ACTIVE = 1 << 6,
CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL = 1 << 7,
};
-typedef uint32_t clap_transport_flags;
typedef struct clap_event_transport {
- alignas(4) clap_transport_flags flags;
+ alignas(4) clap_event_header_t header;
+
+ alignas(4) uint32_t flags; // see clap_transport_flags
alignas(8) clap_beattime song_pos_beats; // position in beats
alignas(8) clap_sectime song_pos_seconds; // position in seconds
@@ -146,58 +203,45 @@ typedef struct clap_event_transport {
alignas(2) int16_t tsig_denom; // time signature denominator
} clap_event_transport_t;
-typedef struct clap_event_note_mask {
- uint32_t port_index;
-
- // bitset of active keys:
- // - 11 bits
- // - root note is not part of the bitset
- // - bit N is: root note + N + 1
- // 000 0100 0100 -> minor chord
- // 000 0100 1000 -> major chord
- // 010 1011 0101 -> locrian scale
- alignas(2) uint16_t note_mask;
- alignas(1) uint8_t root_note; // 0..11, 0 for C
-} clap_event_note_mask_t;
-
typedef struct clap_event_midi {
- alignas(4) uint32_t port_index;
+ alignas(4) clap_event_header_t header;
+
+ alignas(2) uint16_t port_index;
alignas(1) uint8_t data[3];
} clap_event_midi_t;
typedef struct clap_event_midi_sysex {
- alignas(4) uint32_t port_index;
+ alignas(4) clap_event_header_t header;
+
+ alignas(2) uint16_t port_index;
const uint8_t *buffer; // midi buffer
alignas(4) uint32_t size;
} clap_event_midi_sysex_t;
-typedef struct clap_event {
- alignas(4) clap_event_type type;
- alignas(4) uint32_t time; // offset from the first sample in the process block
-
- union {
- clap_event_note_t note;
- clap_event_note_expression_t note_expression;
- clap_event_param_value_t param_value;
- clap_event_param_mod_t param_mod;
- clap_event_transport_t time_info;
- clap_event_note_mask_t note_mask;
- clap_event_midi_t midi;
- clap_event_midi_sysex_t midi_sysex;
- };
-} clap_event_t;
-
-typedef struct clap_event_list {
+typedef struct clap_event_midi2 {
+ alignas(4) clap_event_header_t header;
+
+ alignas(2) uint16_t port_index;
+ alignas(4) uint32_t data[4];
+} clap_event_midi2_t;
+
+// Input event list, events must be sorted by time.
+typedef struct clap_input_events {
void *ctx; // reserved pointer for the list
- uint32_t (*size)(const struct clap_event_list *list);
+ uint32_t (*size)(const struct clap_input_events *list);
// Don't free the return event, it belongs to the list
- const clap_event_t *(*get)(const struct clap_event_list *list, uint32_t index);
+ const clap_event_header_t *(*get)(const struct clap_input_events *list, uint32_t index);
+} clap_input_events_t;
+
+// Output event list, events must be sorted by time.
+typedef struct clap_output_events {
+ void *ctx; // reserved pointer for the list
- // Makes a copy of the event
- void (*push_back)(const struct clap_event_list *list, const clap_event_t *event);
-} clap_event_list_t;
+ // Pushes a copy of the event
+ void (*push_back)(const struct clap_output_events *list, const clap_event_header_t *event);
+} clap_output_events_t;
#pragma pack(pop)
diff --git a/include/clap/ext/draft/ambisonic.h b/include/clap/ext/draft/ambisonic.h
@@ -0,0 +1,49 @@
+#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.draft/0";
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push, CLAP_ALIGN)
+
+enum {
+ // FuMa channel ordering
+ CLAP_AMBISONIC_FUMA = 0,
+
+ // ACN channel ordering
+ CLAP_AMBISONIC_ACN = 1,
+};
+
+typedef struct clap_ambisonic_info {
+ alignas(4) uint32_t ordering;
+ alignas(1) bool is_normalized;
+} clap_ambisonic_info_t;
+
+typedef struct clap_plugin_ambisonic {
+ // Returns true on success
+ // [main-thread]
+ bool (*get_info)(const clap_plugin_t *plugin,
+ bool is_input,
+ uint32_t port_index,
+ clap_ambisonic_info_t *info);
+
+} clap_plugin_ambisonic_t;
+
+typedef struct clap_host_ambisonic {
+ // Informs the host that the info have changed.
+ // The info can only change when the plugin is de-activated.
+ // [main-thread]
+ void (*changed)(const clap_host_t *host);
+} clap_host_ambisonic_t;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/clap/ext/event-filter.h b/include/clap/ext/event-filter.h
@@ -17,7 +17,7 @@ extern "C" {
typedef struct clap_plugin_event_filter {
// Returns true if the plugin is interested in the given event type.
// [main-thread]
- bool (*accepts)(const clap_plugin_t *plugin, clap_event_type event_type);
+ bool (*accepts)(const clap_plugin_t *plugin, uint16_t space_id, uint16_t event_type);
} clap_plugin_event_filter_t;
diff --git a/include/clap/ext/event-registry.h b/include/clap/ext/event-registry.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "../plugin.h"
+
+static CLAP_CONSTEXPR const char CLAP_EXT_EVENT_REGISTRY[] = "clap.event-registry";
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push, CLAP_ALIGN)
+
+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 to UINT16_MAX if the space name is unknown to the host.
+ // [main-thread]
+ bool (*query)(const clap_host_t *host, const char *space_name, uint16_t *space_id);
+} clap_host_event_registry_t;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/clap/ext/fd-support.h b/include/clap/ext/fd-support.h
@@ -1,52 +0,0 @@
-#pragma once
-
-#include "../plugin.h"
-
-static CLAP_CONSTEXPR const char CLAP_EXT_FD_SUPPORT[] = "clap.fd-support";
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#pragma pack(push, CLAP_ALIGN)
-
-#ifdef _WIN32
-typedef void *clap_fd;
-#else
-typedef int clap_fd;
-#endif
-
-enum {
- // IO events
- CLAP_FD_READ = 1 << 0,
- CLAP_FD_WRITE = 1 << 1,
- CLAP_FD_ERROR = 1 << 2,
-};
-typedef uint32_t clap_fd_flags;
-
-typedef struct clap_plugin_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 writting.
- //
- // [main-thread]
- void (*on_fd)(const clap_plugin_t *plugin, clap_fd fd, clap_fd_flags flags);
-} clap_plugin_fd_support_t;
-
-typedef struct clap_host_fd_support {
- // [main-thread]
- bool (*register_fd)(const clap_host_t *host, clap_fd fd, clap_fd_flags flags);
-
- // [main-thread]
- bool (*modify_fd)(const clap_host_t *host, clap_fd fd, clap_fd_flags flags);
-
- // [main-thread]
- bool (*unregister_fd)(const clap_host_t *host, clap_fd fd);
-} clap_host_fd_support_t;
-
-#pragma pack(pop)
-
-#ifdef __cplusplus
-}
-#endif
-\ No newline at end of file
diff --git a/include/clap/ext/gui.h b/include/clap/ext/gui.h
@@ -41,9 +41,13 @@ typedef struct clap_plugin_gui {
// [main-thread]
void (*destroy)(const clap_plugin_t *plugin);
- // Set the absolute GUI scaling factor.
- // [main-thread]
- void (*set_scale)(const clap_plugin_t *plugin, double scale);
+ // Set the absolute GUI scaling factor, and override any OS info.
+ // If the plugin does not provide this function, then it should work out the scaling factor
+ // itself by querying the OS directly.
+ //
+ // Return false if the plugin can't apply the scaling; true on success.
+ // [main-thread,optional]
+ bool (*set_scale)(const clap_plugin_t *plugin, double scale);
// Get the current size of the plugin UI, with the scaling applied.
// clap_plugin_gui->create() must have been called prior to asking the size.
@@ -79,8 +83,18 @@ typedef struct clap_plugin_gui {
typedef struct clap_host_gui {
/* Request the host to resize the client area to width, height.
* Return true on success, false otherwise.
- * [thread-safe] */
- bool (*resize)(const clap_host_t *host, uint32_t width, uint32_t height);
+ * [main-thread] */
+ bool (*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.
+ * [main-thread] */
+ bool (*request_show)(const clap_host_t *host);
+
+ /* Request the host to hide the plugin gui.
+ * Return true on success, false otherwise.
+ * [main-thread] */
+ bool (*request_hide)(const clap_host_t *host);
} clap_host_gui_t;
#pragma pack(pop)
diff --git a/include/clap/ext/note-ports.h b/include/clap/ext/note-ports.h
@@ -19,9 +19,17 @@ extern "C" {
#pragma pack(push, CLAP_ALIGN)
+enum clap_note_dialect {
+ CLAP_NOTE_DIALECT_CLAP = 1 << 0,
+ CLAP_NOTE_DIALECT_MIDI = 1 << 1,
+ CLAP_NOTE_DIALECT_MIDI2 = 1 << 2,
+};
+
typedef struct clap_note_port_info {
- alignas(4) clap_id id; // stable identifier
- alignas(1) char name[CLAP_NAME_SIZE]; // displayable name, i18n?
+ alignas(4) clap_id id; // stable identifier
+ alignas(4) uint32_t clap_supported_dialects; // bitfield, see clap_note_dialect
+ alignas(4) uint32_t clap_preferred_dialect; // one value of clap_note_dialect
+ alignas(1) char name[CLAP_NAME_SIZE]; // displayable name, i18n?
} clap_note_port_info_t;
// The audio ports scan has to be done while the plugin is deactivated.
diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h
@@ -189,9 +189,9 @@ typedef struct clap_plugin_params {
//
// [active && !processing : audio-thread]
// [!active : main-thread]
- void (*flush)(const clap_plugin_t *plugin,
- const clap_event_list_t *input_parameter_changes,
- const clap_event_list_t *output_parameter_changes);
+ void (*flush)(const clap_plugin_t *plugin,
+ const clap_input_events_t *in,
+ const clap_output_events_t *out);
} clap_plugin_params_t;
enum {
diff --git a/include/clap/ext/posix-fd-support.h b/include/clap/ext/posix-fd-support.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "../plugin.h"
+
+static CLAP_CONSTEXPR const char CLAP_EXT_POSIX_FD_SUPPORT[] = "clap.posix-fd-support";
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push, CLAP_ALIGN)
+
+enum {
+ // IO events flags
+ CLAP_POSIX_FD_READ = 1 << 0,
+ CLAP_POSIX_FD_WRITE = 1 << 1,
+ CLAP_POSIX_FD_ERROR = 1 << 2,
+};
+
+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 writting.
+ //
+ // [main-thread]
+ void (*on_fd)(const clap_plugin_t *plugin, int fd, int flags);
+} clap_plugin_fd_support_t;
+
+typedef struct clap_host_posix_fd_support {
+ // [main-thread]
+ bool (*register_fd)(const clap_host_t *host, int fd, int flags);
+
+ // [main-thread]
+ bool (*modify_fd)(const clap_host_t *host, int fd, int flags);
+
+ // [main-thread]
+ bool (*unregister_fd)(const clap_host_t *host, int fd);
+} clap_host_posix_fd_support_t;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif
+\ No newline at end of file
diff --git a/include/clap/plugin-factory.h b/include/clap/plugin-factory.h
@@ -13,6 +13,8 @@ extern "C" {
// Every methods must be thread-safe.
// It is very important to be able to scan the plugin as quickly as possible.
+//
+// If the content of the factory may change due to external events, like the user installed
typedef struct clap_plugin_factory {
/* Get the number of plugins available.
* [thread-safe] */
diff --git a/include/clap/plugin.h b/include/clap/plugin.h
@@ -12,27 +12,6 @@ extern "C" {
#pragma pack(push, CLAP_ALIGN)
-/* bitfield
- * This gives an hint to the host what the plugin might do. */
-enum {
- /* Instruments can play notes, and generate audio */
- CLAP_PLUGIN_INSTRUMENT = (1 << 0),
-
- /* Audio effects, process audio input and produces audio.
- * Exemple: delay, reverb, compressor. */
- CLAP_PLUGIN_AUDIO_EFFECT = (1 << 1),
-
- /* Event effects, takes events as input and produces events.
- * Exemple: arpegiator */
- CLAP_PLUGIN_EVENT_EFFECT = (1 << 2), // can be seen as midi effect
-
- // Analyze audio and/or events.
- // If this is the only type reported by the plugin, the host can assume that it wont change the
- // audio and event signal.
- CLAP_PLUGIN_ANALYZER = (1 << 3),
-};
-typedef int32_t clap_plugin_type;
-
typedef struct clap_plugin_descriptor {
clap_version_t clap_version; // initialized to CLAP_VERSION
@@ -47,16 +26,25 @@ typedef struct clap_plugin_descriptor {
// Arbitrary list of keywords, separated by `;'
// They can be matched by the host search engine and used to classify the plugin.
+ //
+ // Some pre-defined keywords:
+ // - "instrument", "audio_effect", "note_effect", "analyzer"
+ // - "mono", "stereo", "surround", "ambisonic"
+ // - "distortion", "compressor", "limiter", "transient"
+ // - "equalizer", "filter", "de-esser"
+ // - "delay", "reverb", "chorus", "flanger"
+ // - "tool", "utility", "glitch"
+ //
+ // - "win32-dpi-aware" informs the host that this plugin is dpi-aware on Windows
+ //
// Some examples:
- // "master;eq;spectrum"
- // "compressor;analog;character"
- // "reverb;plate;cathedral"
- // "kick;analog;808;roland"
- // "analog;character;roland;moog"
- // "chip;chiptune;gameboy;nintendo;sega"
- const char *keywords;
-
- alignas(8) uint64_t plugin_type; // bitfield of clap_plugin_type
+ // "equalizer;analyzer;stereo;mono"
+ // "compressor;analog;character;mono"
+ // "reverb;plate;stereo"
+ // "reverb;spring;surround"
+ // "kick;analog;808;roland;drum;mono;instrument"
+ // "instrument;chiptune;gameboy;nintendo;sega;mono"
+ const char *features;
} clap_plugin_descriptor_t;
typedef struct clap_plugin {
@@ -66,10 +54,12 @@ typedef struct clap_plugin {
// Must be called after creating the plugin.
// If init returns false, the host must destroy the plugin instance.
+ // [main-thread]
bool (*init)(const struct clap_plugin *plugin);
- /* Free the plugin and its resources.
- * It is not required to deactivate the plugin prior to this call. */
+ // Free the plugin and its resources.
+ // It is not required to deactivate the plugin prior to this call.
+ // [main-thread & !active]
void (*destroy)(const struct clap_plugin *plugin);
// Activate and deactivate the plugin.
@@ -78,25 +68,29 @@ typedef struct clap_plugin {
// the [min, max] range, which is bounded by [1, INT32_MAX].
// Once activated the latency and port configuration must remain constant, until deactivation.
//
- // [main-thread]
+ // [main-thread & !active_state]
bool (*activate)(const struct clap_plugin *plugin,
double sample_rate,
uint32_t min_frames_count,
uint32_t max_frames_count);
+ // [main-thread & active_state]
void (*deactivate)(const struct clap_plugin *plugin);
- // Set to true before processing, and to false before sending the plugin to sleep.
- // [audio-thread]
+ // Call start processing before processing.
+ // [audio-thread & active_state & !processing_state]
bool (*start_processing)(const struct clap_plugin *plugin);
+
+ // Call stop processing before sending the plugin to sleep.
+ // [audio-thread & active_state & processing_state]
void (*stop_processing)(const struct clap_plugin *plugin);
- /* process audio, events, ...
- * [audio-thread] */
+ // process audio, events, ...
+ // [audio-thread & active_state & processing_state]
clap_process_status (*process)(const struct clap_plugin *plugin, const clap_process_t *process);
- /* Query an extension.
- * The returned pointer is owned by the plugin.
- * [thread-safe] */
+ // Query an extension.
+ // The returned pointer is owned by the plugin.
+ // [thread-safe]
const void *(*get_extension)(const struct clap_plugin *plugin, const char *id);
// Called by the host on the main thread in response to a previous call to:
diff --git a/include/clap/process.h b/include/clap/process.h
@@ -28,8 +28,17 @@ enum {
typedef int32_t clap_process_status;
typedef struct clap_process {
- alignas(8) uint64_t steady_time; // a steady sample time counter, requiered
- alignas(4) uint32_t frames_count; // number of frame to process
+ // A steady sample time counter.
+ // This field can be used to calculate the sleep duration between two process calls.
+ // This value may be specific to this plugin instance and have no relation to what
+ // other plugin instances may receive.
+ //
+ // Set to -1 if not available, otherwise the value must be greater or equal to 0,
+ // and must be increased by at least `frames_count` for the next call to process.
+ alignas(8) int64_t steady_time;
+
+ // Number of frame to process
+ alignas(4) uint32_t frames_count;
// time info at sample 0
// If null, then this is a free running host, no transport events will be provided
@@ -46,9 +55,15 @@ typedef struct clap_process {
alignas(4) uint32_t audio_inputs_count;
alignas(4) uint32_t audio_outputs_count;
- /* events */
- const clap_event_list_t *in_events;
- const clap_event_list_t *out_events;
+ // Input and output events.
+ //
+ // Events must be sorted by time.
+ // The input event list can't be modified.
+ //
+ // If a plugin does not implement clap_plugin_note_ports,
+ // then it gets a default note input and output.
+ const clap_input_events_t *in_events;
+ const clap_output_events_t *out_events;
} clap_process_t;
#pragma pack(pop)
diff --git a/include/clap/version.h b/include/clap/version.h
@@ -20,19 +20,19 @@ typedef struct clap_version {
#pragma pack(pop)
-static const uint32_t CLAP_VERSION_MAJOR = 0;
-static const uint32_t CLAP_VERSION_MINOR = 16;
-static const uint32_t CLAP_VERSION_REVISION = 1;
+#ifdef __cplusplus
+}
+#endif
+
+static CLAP_CONSTEXPR const uint32_t CLAP_VERSION_MAJOR = 0;
+static CLAP_CONSTEXPR const uint32_t CLAP_VERSION_MINOR = 17;
+static CLAP_CONSTEXPR const uint32_t CLAP_VERSION_REVISION = 0;
-static const clap_version_t CLAP_VERSION = {
+static CLAP_CONSTEXPR const clap_version_t CLAP_VERSION = {
CLAP_VERSION_MAJOR, CLAP_VERSION_MINOR, CLAP_VERSION_REVISION};
// For version 0, we require the same minor version because
// we may still break the ABI at this point
-static inline bool clap_version_is_compatible(const clap_version_t v) {
+static CLAP_CONSTEXPR inline bool clap_version_is_compatible(const clap_version_t v) {
return v.major == CLAP_VERSION_MAJOR && v.minor == CLAP_VERSION_MINOR;
-}
-
-#ifdef __cplusplus
-}
-#endif
-\ No newline at end of file
+}
+\ No newline at end of file