commit df8f16c69ba1c1a15fb105f0c5a2e5b9ac6be742
parent e292447bd0dbb265ef091178bfed9e29617ebb5b
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Mon, 22 Jan 2024 10:30:27 +0100
Merge pull request #371 from free-audio/next
CLAP 1.2.0
Diffstat:
53 files changed, 1650 insertions(+), 1273 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -50,6 +50,7 @@ add_custom_target(clap-tests)
if (${CLAP_BUILD_TESTS})
message(STATUS "Including CLAP tests, compile tests, and versions")
+ include(CheckIncludeFile)
macro(clap_compile_cpp SUFFIX EXT STDC STDCPP)
add_executable(clap-compile-${SUFFIX} EXCLUDE_FROM_ALL src/main.${EXT})
@@ -84,11 +85,17 @@ if (${CLAP_BUILD_TESTS})
clap_compile_cpp(cpp17 cc 17 17)
clap_compile_cpp(cpp20 cc 17 20)
+ check_include_file(threads.h CLAP_HAS_THREADS_H)
+
add_library(clap-plugin-template MODULE EXCLUDE_FROM_ALL src/plugin-template.c)
target_link_libraries(clap-plugin-template PRIVATE clap)
set_target_properties(clap-plugin-template PROPERTIES C_STANDARD 11)
add_dependencies(clap-tests clap-plugin-template)
+ if(CLAP_HAS_THREADS_H)
+ target_compile_definitions(clap-plugin-template PRIVATE CLAP_HAS_THREADS_H)
+ endif()
+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(clap-plugin-template PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/linux-my_plug.version)
target_link_libraries(clap-plugin-template PRIVATE -Wl,-z,defs)
diff --git a/ChangeLog.md b/ChangeLog.md
@@ -1,3 +1,77 @@
+# Changes in 1.2.0
+
+## New conventions
+
+* [extension-id](conventions/extension-id.md): introduce some rules about extension ID naming.
+
+## Stabilize extensions
+
+* `CLAP_EXT_AMBISONIC`
+* `CLAP_EXT_AUDIO_PORTS_ACTIVATION`
+* `CLAP_EXT_CONFIGURABLE_AUDIO_PORTS`
+* `CLAP_EXT_CONTEXT_MENU`
+* `CLAP_EXT_PARAM_INDICATION`
+* `CLAP_EXT_PRESET_LOAD`
+* `CLAP_EXT_REMOTE_CONTROLS`
+* `CLAP_EXT_STATE_CONTEXT`
+* `CLAP_EXT_SURROUND`
+* `CLAP_EXT_TRACK_INFO`
+
+### Notes regarding extension ID change after draft stabilization
+
+We changed the extension ID in the process of stabilization which leads to a **break**.
+
+To mitigate this transition, we've provided compatibility extension IDs which can be used to match and use the latest draft extensions as they are 100% compatible.
+
+For example, `CLAP_EXT_CONTEXT_MENU` for the stable ID and `CLAP_EXT_CONTEXT_MENU_COMPAT` for the draft ID.
+
+As you can see in [extension-id](conventions/extension-id.md), we introduced some rules, so this kind of break won't happen again.
+
+We may decide to remove the `*_COMPAT` IDs in the future once their usage becomes antiquated.
+
+## Removed draft extensions
+
+* `CLAP_EXT_CHECK_FOR_UPDATE` wasn't used and it's design needed more thought.
+* `CLAP_EXT_MIDI_MAPPING` wasn't used. MIDI2 seems to do it better, and the interface wasn't satisfying.
+* `CLAP_EXT_CV` the interface wasn't satisfying.
+
+## Stabilize factory
+
+* `CLAP_PRESET_DISCOVERY_FACTORY_ID`
+
+Note: we kept the last draft factory ID in order to not break plugins already using it.
+
+## Plugin State Converter
+
+* Introduction of a new factory which provides a plugin state convertion mechanism.
+
+## Refactoring
+
+* `clap_plugin_id_t` was renamed to `clap_universal_plugin_id_t` to make it clear that it can describe more than just a CLAP plugin ID.
+* `clap_timestamp_t` was renamed to `clap_timestamp` to be consistent with other types, like e.g. `clap_id`. Also it was moved to a separate header as `CLAP_PRESET_DISCOVERY_FACTORY_ID` was stabilized.
+
+## Documentation
+
+* [events.h](include/clap/events.h): Clarify how "Port Channel Key NoteID" matching works
+* [events.h](include/clap/events.h): Clarify how `clap_event_note` fields map to MIDI, Host, etc...
+* [events.h](include/clap/events.h): Expand clap note expression documentation
+* [plugin.h](include/clap/plugin.h): Style cleanup
+* [params.h](include/clap/ext/params.h): Fix incorrect function name reference
+* [latency.h](include/clap/ext/latency.h): Require the plugin to be activated to get the latency and clarify that the latency can only be fetched when the plugin is activated
+
+## Plugin Template
+
+* [plugin-template.c](src/plugin-template.c): implement thread-safe plugin entry init counter
+
+## Organization
+
+* `clap.h` no longer includes headers from `ext/draft` or `factory/draft`. Draft extension and factory headers must now be explicitly included, either individually or via the `all.h` header.
+
+## Other changes
+
+* [voice-info.h](include/clap/ext/voice-info.h): Make the voice info id `CLAP_CONSTEXPR` like all other ids
+* [preset-load.h](include/clap/ext/preset-load.h): Make the preset load id and compat id `CLAP_CONSTEXPR` like all other ids
+
# Changes in 1.1.10
* [params.h](include/clap/ext/params.h): add `CLAP_PARAM_IS_ENUM` flag.
diff --git a/README.md b/README.md
@@ -11,7 +11,7 @@
- [Extensions](#extensions)
- [Fundamental extensions](#fundamental-extensions)
- [Support extensions](#support-extensions)
- - [Extra extensions](#extra-extensions)
+ - [Deeper Host integration](#deeper-host-integration)
- [Third-party extensions](#third-party-extensions)
- [Adapters](#adapters)
- [Resources](#resources)
@@ -32,6 +32,7 @@ that is, a plugin binary compiled with CLAP 1.x can be loaded by any other
CLAP 1.y.
To work with CLAP, include [clap/clap.h](include/clap/clap.h).
+To also include the draft extensions, include [clap/all.h](include/clap/all.h).
The two most important objects are `clap_host` and `clap_plugin`.
@@ -81,34 +82,44 @@ You can create your own extensions and share them. Make sure that the extension
This is a list of the extensions that you most likely want to implement
and use to get a basic plugin experience:
-- [log](include/clap/ext/log.h), lets the host aggregate plugin logs
-- [thread-check](include/clap/ext/thread-check.h), check which thread you are currently on, useful for correctness validation
-- [audio-ports](include/clap/ext/audio-ports.h), define the audio ports
-- [note-ports](include/clap/ext/note-ports.h), define the note ports
+- [state](include/clap/ext/state.h), save and load the plugin state
+ - [state-context](include/clap/ext/state-context.h), same as state but with additional context info (preset, duplicate, project)
+ - [resource-directory](include/clap/ext/draft/resource-directory.h), host provided folder for the plugin to save extra resource like multi-samples, ... (draft)
- [params](include/clap/ext/params.h), parameters management
-- [latency](include/clap/ext/latency.h), report the plugin latency
+- [note-ports](include/clap/ext/note-ports.h), define the note ports
+- [audio-ports](include/clap/ext/audio-ports.h), define the audio ports
+ - [surround](include/clap/ext/surround.h), inspect surround channel mapping
+ - [ambisonic](include/clap/ext/draft/ambisonic.h), inspect ambisonic channel mapping
+ - [configurable-audio-ports](include/clap/ext/configurable-audio-ports.h), request the plugin to apply a given configuration
+ - [audio-ports-config](include/clap/ext/audio-ports-config.h), simple list of pre-defined audio ports configurations, meant to be exposed to the user
+ - [audio-ports-activation](include/clap/ext/audio-ports-activation.h), activate and deactivate a given audio port
+ - [extensible-audio-ports](include/clap/ext/draft/extensible-audio-ports.h), let the host add audio ports to the plugin, this is useful for dynamic number of audio inputs (draft)
- [render](include/clap/ext/render.h), renders realtime or offline
+- [latency](include/clap/ext/latency.h), report the plugin latency
- [tail](include/clap/ext/tail.h), processing tail length
-- [state](include/clap/ext/state.h), save and load the plugin state
- [gui](include/clap/ext/gui.h), generic gui controller
+- [voice-info](include/clap/ext/voice-info.h), let the host know how many voices the plugin has, this is important for polyphonic modulations
+- [track-info](include/clap/ext/track-info.h), give some info to the plugin about the track it belongs to
+- [tuning](include/clap/ext/draft/tuning.h), host provided microtuning (draft)
+- [triggers](include/clap/ext/draft/triggers.h), plugin's triggers, similar to parameters but stateless
## Support extensions
+- [thread-check](include/clap/ext/thread-check.h), check which thread you are currently on, useful for correctness validation
- [thread-pool](include/clap/ext/thread-pool.h), use the host thread pool
+- [log](include/clap/ext/log.h), lets the host aggregate plugin logs
- [timer-support](include/clap/ext/timer-support.h), lets the plugin register timer handlers
- [posix-fd-support](include/clap/ext/posix-fd-support.h), lets the plugin register I/O handlers
-## Extra extensions
+## Deeper Host integration
+- [remote-controls](include/clap/ext/remote-controls.h), bank of controls that can be mapped on a controlles with 8 knobs
+- [preset-discovery](include/clap/factory/preset-discovery.h), let the host index the plugin's preset in their native file format
+- [preset-load](include/clap/ext/preset-load.h), let the host ask the plugin to load a preset
+- [param-indication](include/clap/ext/param-indication.h), let the plugin know when a physical control is mapped to a parameter and if there is automation data
- [note-name](include/clap/ext/note-name.h), give a name to notes, useful for drum machines
-- [tuning](include/clap/ext/draft/tuning.h), host provided microtuning
-- [track-info](include/clap/ext/draft/track-info.h)
-- [quick-controls](include/clap/ext/draft/quick-controls.h), bank of controls that can be mapped on a controlles with 8 knobs
-- [file-reference](include/clap/ext/draft/file-reference.h), let the host know about the plugin's file reference, and perform "Collect & Save"
-- [check-for-update](include/clap/ext/draft/check-for-update.h), check if there is a new version of a plugin
-- [audio-ports-config](include/clap/ext/audio-ports-config.h), simple list of possible configurations
-- [surround](include/clap/ext/draft/surround.h), inspect surround channel mapping
-- [ambisonic](include/clap/ext/draft/ambisonic.h), inspect ambisonic channel mapping
+- [transport-control](include/clap/ext/draft/transport-control.h), let the plugin control the host's transport (draft)
+- [context-menu](include/clap/ext/context-menu.h), exchange context menu entries between host and plugin, let the plugin ask the host to popup its own context menu
## Third-party extensions
diff --git a/conventions/extension-id.md b/conventions/extension-id.md
@@ -0,0 +1,32 @@
+# Extension ID
+
+## Naming
+
+The extension shall be named in the form: `clap.$NAME/$REV`.
+Where:
+- `$NAME` is the name of the exension.
+- `$REV` is the revision of the extension. This is an integer that is incremented for each iteration. It should start at 1.
+
+For extensions made by third-parties and not officially published by the CLAP project, please use the following form: `$REVERSE_URI.$NAME/$REV`.
+Where:
+- `$REVERSE_URI` would be something like `com.bitwig`.
+
+## Draft
+
+An extension is considered a draft extension if it is in the [draft](../include/clap/ext/draft/) folder.
+Make sure to also include it in [all.h](../include/clap/all.h).
+
+When the extension is migrating from draft to stable, its extension ID must not change.
+Move its inclusion from [all.h](../include/clap/all.h) into [clap.h](../include/clap/clap.h).
+
+All extensions must go though the draft phase first.
+
+## For factory ID
+
+Everything about the extension id symmetrically applies to factory id.
+
+## History
+
+Before version 1.2.0 when this document was written, existing extensions didn't honor these rules.
+We wanted to stabilize some draft extensions without breaking compatibility, yet their extension IDs contained the string `draft`.
+While these strings weren't user-facing, we still wanted to remove them, so we updated the extension IDs according to this document and introduced IDs with `_COMPAT` suffixes to provide backward compatibility with the draft versions.
diff --git a/include/clap/all.h b/include/clap/all.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "clap.h"
+
+#include "factory/draft/plugin-invalidation.h"
+#include "factory/draft/plugin-state-converter.h"
+
+#include "ext/draft/extensible-audio-ports.h"
+#include "ext/draft/resource-directory.h"
+#include "ext/draft/transport-control.h"
+#include "ext/draft/triggers.h"
+#include "ext/draft/tuning.h"
diff --git a/include/clap/clap.h b/include/clap/clap.h
@@ -28,44 +28,37 @@
#include "entry.h"
#include "factory/plugin-factory.h"
-#include "factory/draft/plugin-invalidation.h"
-#include "factory/draft/preset-discovery.h"
+#include "factory/preset-discovery.h"
#include "plugin.h"
#include "plugin-features.h"
#include "host.h"
+#include "universal-plugin-id.h"
+#include "ext/ambisonic.h"
+#include "ext/audio-ports-activation.h"
#include "ext/audio-ports-config.h"
#include "ext/audio-ports.h"
+#include "ext/configurable-audio-ports.h"
+#include "ext/context-menu.h"
#include "ext/event-registry.h"
#include "ext/gui.h"
#include "ext/latency.h"
#include "ext/log.h"
#include "ext/note-name.h"
#include "ext/note-ports.h"
+#include "ext/param-indication.h"
#include "ext/params.h"
#include "ext/posix-fd-support.h"
+#include "ext/preset-load.h"
+#include "ext/remote-controls.h"
#include "ext/render.h"
+#include "ext/state-context.h"
#include "ext/state.h"
+#include "ext/surround.h"
#include "ext/tail.h"
#include "ext/thread-check.h"
#include "ext/thread-pool.h"
#include "ext/timer-support.h"
+#include "ext/track-info.h"
#include "ext/voice-info.h"
-
-#include "ext/draft/ambisonic.h"
-#include "ext/draft/audio-ports-activation.h"
-#include "ext/draft/context-menu.h"
-#include "ext/draft/cv.h"
-#include "ext/draft/midi-mappings.h"
-#include "ext/draft/param-indication.h"
-#include "ext/draft/preset-load.h"
-#include "ext/draft/remote-controls.h"
-#include "ext/draft/resource-directory.h"
-#include "ext/draft/state-context.h"
-#include "ext/draft/surround.h"
-#include "ext/draft/track-info.h"
-#include "ext/draft/triggers.h"
-#include "ext/draft/tuning.h"
-#include "ext/draft/configurable-audio-ports.h"
-#include "ext/draft/extensible-audio-ports.h"
diff --git a/include/clap/entry.h b/include/clap/entry.h
@@ -31,34 +31,100 @@ extern "C" {
// Each directory should be recursively searched for files and/or bundles as appropriate in your OS
// ending with the extension `.clap`.
//
-// Every method must be thread-safe.
+// init and deinit in most cases are called once, in a matched pair, when the dso is loaded / unloaded.
+// In some rare situations it may be called multiple times in a process, so the functions must be defensive,
+// mutex locking and counting calls if undertaking non trivial non idempotent actions.
+//
+// Rationale:
+//
+// The intent of the init() and deinit() functions is to provide a "normal" initialization patterh
+// which occurs when the shared object is loaded or unloaded. As such, hosts will call each once and
+// in matched pairs. In CLAP specifications prior to 1.2.0, this single-call was documented as a
+// requirement.
+//
+// We realized, though, that this is not a requirement hosts can meet. If hosts load a plugin
+// which itself wraps another CLAP for instance, while also loading that same clap in its memory
+// space, both the host and the wrapper will call init() and deinit() and have no means to communicate
+// the state.
+//
+// With CLAP 1.2.0 and beyond we are changing the spec to indicate that a host should make an
+// absolute best effort to call init() and deinit() once, and always in matched pairs (for every
+// init() which returns true, one deinit() should be called).
+//
+// This takes the de-facto burden on plugin writers to deal with multiple calls into a hard requirement.
+//
+// Most init() / deinit() pairs we have seen are the relatively trivial {return true;} and {}. But
+// if your init() function does non-trivial one time work, the plugin author must maintain a counter
+// and must manage a mutex lock. The most obvious implementation will maintain a static counter and a
+// global mutex, increment the counter on each init, decrement it on each deinit, and only undertake
+// the init or deinit action when the counter is zero.
typedef struct clap_plugin_entry {
clap_version_t clap_version; // initialized to CLAP_VERSION
- // This function must be called first, and can only be called once.
+ // Initializes the DSO.
+ //
+ // This function must be called first, before any-other CLAP-related function or symbol from this
+ // DSO.
+ //
+ // It also must only be called once, until a later call to deinit() is made, after which init()
+ // can be called once more to re-initialize the DSO.
+ // This enables hosts to e.g. quickly load and unload a DSO for scanning its plugins, and then
+ // load it again later to actually use the plugins if needed.
+ //
+ // As stated above, even though hosts are forbidden to do so directly, multiple calls before any
+ // deinit() call may still happen. Implementations *should* take this into account, and *must*
+ // do so as of CLAP 1.2.0.
//
// It should be as fast as possible, in order to perform a very quick scan of the plugin
// descriptors.
//
- // It is forbidden to display graphical user interface in this call.
- // It is forbidden to perform user interaction in this call.
+ // It is forbidden to display graphical user interfaces in this call.
+ // It is forbidden to perform any user interaction in this call.
//
// If the initialization depends upon expensive computation, maybe try to do them ahead of time
// and cache the result.
//
- // If init() returns false, then the host must not call deinit() nor any other clap
- // related symbols from the DSO.
+ // Returns true on success. If init() returns false, then the DSO must be considered
+ // uninitialized, and the host must not call deinit() nor any other CLAP-related symbols from the
+ // DSO.
+ // This function also returns true in the case where the DSO is already initialized, and no
+ // actual initialization work is done in this call, as explain above.
//
// plugin_path is the path to the DSO (Linux, Windows), or the bundle (macOS).
+ //
+ // This function may be called on any thread, including a different one from the one a later call
+ // to deinit() (or a later init()) can be made.
+ // However, it is forbidden to call this function simultaneously from multiple threads.
+ // It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the
+ // DSO, including (but not limited to) deinit().
bool(CLAP_ABI *init)(const char *plugin_path);
- // No more calls into the DSO must be made after calling deinit().
+ // De-initializes the DSO, freeing any resources allocated or initialized by init().
+ //
+ // After this function is called, no more calls into the DSO must be made, except calling init()
+ // again to re-initialize the DSO.
+ // This means that after deinit() is called, the DSO can be considered to be in the same state
+ // as if init() was never called at all yet, enabling it to be re-initialized as needed.
+ //
+ // As stated above, even though hosts are forbidden to do so directly, multiple calls before any
+ // new init() call may still happen. Implementations *should* take this into account, and *must*
+ // do so as of CLAP 1.2.0.
+ //
+ // Just like init(), this function may be called on any thread, including a different one from
+ // the one init() was called from, or from the one a later init() call can be made.
+ // However, it is forbidden to call this function simultaneously from multiple threads.
+ // It is also forbidden to call it simultaneously with *any* other CLAP-related symbols from the
+ // DSO, including (but not limited to) deinit().
void(CLAP_ABI *deinit)(void);
// Get the pointer to a factory. See factory/plugin-factory.h for an example.
//
// Returns null if the factory is not provided.
// The returned pointer must *not* be freed by the caller.
+ //
+ // Unlike init() and deinit(), this function can be called simultaneously by multiple threads.
+ //
+ // [thread-safe]
const void *(CLAP_ABI *get_factory)(const char *factory_id);
} clap_plugin_entry_t;
diff --git a/include/clap/events.h b/include/clap/events.h
@@ -117,19 +117,62 @@ enum {
};
// Note on, off, end and choke events.
+//
+// Clap addresses notes and voices using the 4-value tuple
+// (port, channel, key, note_id). Note on/off/end/choke
+// events and parameter modulation messages are delivered with
+// these values populated.
+//
+// Values in a note and voice address are either >= 0 if they
+// are specified, or -1 to indicate a wildcard. A wildcard
+// means a voice with any value in that part of the tuple
+// matches the message.
+//
+// For instance, a (PCKN) of (0, 3, -1, -1) will match all voices
+// on channel 3 of port 0. And a PCKN of (-1, 0, 60, -1) will match
+// all channel 0 key 60 voices, independent of port or note id.
+//
+// Especially in the case of note-on note-off pairs, and in the
+// absence of voice stacking or polyphonic modulation, a host may
+// choose to issue a note id only at note on. So you may see a
+// message stream like
+//
+// CLAP_EVENT_NOTE_ON [0,0,60,184]
+// CLAP_EVENT_NOTE_OFF [0,0,60,-1]
+//
+// and the host will expect the first voice to be released.
+// Well constructed plugins will search for voices and notes using
+// the entire tuple.
+//
// In the case of note choke or end events:
// - the velocity is ignored.
-// - key and channel are used to match active notes, a value of -1 matches all.
+// - key and channel are used to match active notes
+// - note_id is optionally provided by the host
typedef struct clap_event_note {
clap_event_header_t header;
- int32_t note_id; // -1 if unspecified, otherwise >=0
- int16_t port_index;
- int16_t channel; // 0..15
- int16_t key; // 0..127
+ int32_t note_id; // host provided note id >= 0, or -1 if unspecified or wildcard
+ int16_t port_index; // port index from ext/note-ports; -1 for wildcard
+ int16_t channel; // 0..15, same as MIDI1 Channel Number, -1 for wildcard
+ int16_t key; // 0..127, same as MIDI1 Key Number (60==Middle C), -1 for wildcard
double velocity; // 0..1
} clap_event_note_t;
+// Note Expressions are well named modifications of a voice targeted to
+// voices using the same wildcard rules described above. Note Expressions are delivered
+// as sample accurate events and should be applied at the sample when received.
+//
+// Note expressions are a statement of value, not cumulative. A PAN event of 0 followed by 1
+// followed by 0.5 would pan hard left, hard right, and center. They are intended as
+// an offset from the non-note-expression voice default. A voice which had a volume of
+// -20db absent note expressions which received a +4db note expression would move the
+// voice to -16db.
+//
+// A plugin which receives a note expression at the same sample as a NOTE_ON event
+// should apply that expression to all generated samples. A plugin which receives
+// a note expression after a NOTE_ON event should initiate the voice with default
+// values and then apply the note expression when received. A plugin may make a choice
+// to smooth note expression streams.
enum {
// with 0 < x <= 4, plain = 20 * log(x)
CLAP_NOTE_EXPRESSION_VOLUME = 0,
@@ -137,7 +180,9 @@ enum {
// pan, 0 left, 0.5 center, 1 right
CLAP_NOTE_EXPRESSION_PAN = 1,
- // relative tuning in semitone, from -120 to +120
+ // Relative tuning in semitones, from -120 to +120. Semitones are in
+ // equal temperament and are doubles; the resulting note would be
+ // retuned by `100 * evt->value` cents.
CLAP_NOTE_EXPRESSION_TUNING = 2,
// 0..1
@@ -153,7 +198,8 @@ typedef struct clap_event_note_expression {
clap_note_expression expression_id;
- // target a specific note_id, port, key and channel, -1 for global
+ // target a specific note_id, port, key and channel, with
+ // -1 meaning wildcard, per the wildcard discussion above
int32_t note_id;
int16_t port_index;
int16_t channel;
@@ -169,7 +215,8 @@ typedef struct clap_event_param_value {
clap_id param_id; // @ref clap_param_info.id
void *cookie; // @ref clap_param_info.cookie
- // target a specific note_id, port, key and channel, -1 for global
+ // target a specific note_id, port, key and channel, with
+ // -1 meaning wildcard, per the wildcard discussion above
int32_t note_id;
int16_t port_index;
int16_t channel;
@@ -185,7 +232,8 @@ typedef struct clap_event_param_mod {
clap_id param_id; // @ref clap_param_info.id
void *cookie; // @ref clap_param_info.cookie
- // target a specific note_id, port, key and channel, -1 for global
+ // target a specific note_id, port, key and channel, with
+ // -1 meaning wildcard, per the wildcard discussion above
int32_t note_id;
int16_t port_index;
int16_t channel;
diff --git a/include/clap/ext/ambisonic.h b/include/clap/ext/ambisonic.h
@@ -0,0 +1,66 @@
+#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
+ //
+ // config_id: the configuration id, see clap_plugin_audio_ports_config.
+ // If config_id is CLAP_INVALID_ID, then this function queries the current port info.
+ // [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
diff --git a/include/clap/ext/audio-ports-activation.h b/include/clap/ext/audio-ports-activation.h
@@ -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
diff --git a/include/clap/ext/audio-ports-config.h b/include/clap/ext/audio-ports-config.h
@@ -26,7 +26,13 @@
/// 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
diff --git a/include/clap/ext/audio-ports.h b/include/clap/ext/audio-ports.h
@@ -54,7 +54,6 @@ typedef struct clap_audio_port_info {
// - CLAP_PORT_STEREO
// - CLAP_PORT_SURROUND (defined in the surround extension)
// - CLAP_PORT_AMBISONIC (defined in the ambisonic extension)
- // - CLAP_PORT_CV (defined in the cv extension)
//
// An extension can provide its own port type and way to inspect the channels.
const char *port_type;
diff --git a/include/clap/ext/configurable-audio-ports.h b/include/clap/ext/configurable-audio-ports.h
@@ -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
diff --git a/include/clap/ext/context-menu.h b/include/clap/ext/context-menu.h
@@ -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
diff --git a/include/clap/ext/draft/ambisonic.h b/include/clap/ext/draft/ambisonic.h
@@ -1,63 +0,0 @@
-#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/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
- //
- // config_id: the configuration id, see clap_plugin_audio_ports_config.
- // If config_id is CLAP_INVALID_ID, then this function queries the current port info.
- // [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
diff --git a/include/clap/ext/draft/audio-ports-activation.h b/include/clap/ext/draft/audio-ports-activation.h
@@ -1,59 +0,0 @@
-#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/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
diff --git a/include/clap/ext/draft/check-for-update.h b/include/clap/ext/draft/check-for-update.h
@@ -1,32 +0,0 @@
-#pragma once
-
-#include "../../plugin.h"
-
-static CLAP_CONSTEXPR const char CLAP_EXT_CHECK_FOR_UPDATE[] = "clap.check_for_update.draft/0";
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct clap_check_for_update_info {
- const char *version; // latest version
- const char *release_date; // YYYY-MM-DD
- const char *url; // url to a download page which the user can visit
-
- bool is_preview; // true if this version is a preview release
-} clap_check_for_update_info_t;
-
-typedef struct clap_plugin_check_for_update {
- // [main-thread]
- void(CLAP_ABI *check)(const clap_plugin_t *plugin, bool include_preview);
-} clap_plugin_check_for_update_t;
-
-typedef struct clap_host_check_for_update {
- // [main-thread]
- void(CLAP_ABI *on_new_version)(const clap_host_t *host,
- const clap_check_for_update_info_t *update_info);
-} clap_host_check_for_update_t;
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/clap/ext/draft/configurable-audio-ports.h b/include/clap/ext/draft/configurable-audio-ports.h
@@ -1,57 +0,0 @@
-#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.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
diff --git a/include/clap/ext/draft/context-menu.h b/include/clap/ext/draft/context-menu.h
@@ -1,164 +0,0 @@
-#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,
- // TODO: kind trigger once the trigger ext is marked as stable
-};
-
-// 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
diff --git a/include/clap/ext/draft/cv.h b/include/clap/ext/draft/cv.h
@@ -1,44 +0,0 @@
-#pragma once
-
-#include "../../plugin.h"
-
-// This extension can be used to specify the cv channel type used by the plugin.
-// Work in progress, suggestions are welcome
-
-static CLAP_CONSTEXPR const char CLAP_EXT_CV[] = "clap.cv.draft/0";
-static CLAP_CONSTEXPR const char CLAP_PORT_CV[] = "cv";
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- // TODO: standardize values?
- CLAP_CV_VALUE = 0,
- CLAP_CV_GATE = 1,
- CLAP_CV_PITCH = 2,
-};
-
-// TODO: maybe we want a channel_info instead, where we could have more details about the supported
-// ranges?
-
-typedef struct clap_plugin_cv {
- // Returns true on success.
- // [main-thread]
- bool(CLAP_ABI *get_channel_type)(const clap_plugin_t *plugin,
- bool is_input,
- uint32_t port_index,
- uint32_t channel_index,
- uint32_t *channel_type);
-} clap_plugin_cv_t;
-
-typedef struct clap_host_cv {
- // Informs the host that the channels type have changed.
- // The channels type can only change when the plugin is de-activated.
- // [main-thread,!active]
- void(CLAP_ABI *changed)(const clap_host_t *host);
-} clap_host_cv_t;
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/clap/ext/draft/extensible-audio-ports.h b/include/clap/ext/draft/extensible-audio-ports.h
@@ -8,7 +8,7 @@ extern "C" {
// 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.draft0";
+ "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.
diff --git a/include/clap/ext/draft/midi-mappings.h b/include/clap/ext/draft/midi-mappings.h
@@ -1,41 +0,0 @@
-#pragma once
-
-#include "../../plugin.h"
-
-static CLAP_CONSTEXPR const char CLAP_EXT_MIDI_MAPPINGS[] = "clap.midi-mappings.draft/0";
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- CLAP_MIDI_MAPPING_CC7,
- CLAP_MIDI_MAPPING_CC14,
- CLAP_MIDI_MAPPING_RPN,
- CLAP_MIDI_MAPPING_NRPN,
-};
-typedef int32_t clap_midi_mapping_type;
-
-typedef struct clap_midi_mapping {
- int32_t channel;
- int32_t number;
- clap_id param_id;
-} clap_midi_mapping_t;
-
-typedef struct clap_plugin_midi_mappings {
- // [main-thread]
- uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
-
- // Returns true on success and stores the result into mapping.
- // [main-thread]
- bool(CLAP_ABI *get)(const clap_plugin_t *plugin, uint32_t index, clap_midi_mapping_t *mapping);
-} clap_plugin_midi_mappings_t;
-
-typedef struct clap_host_midi_mappings {
- // [main-thread]
- void(CLAP_ABI *changed)(const clap_host_t *host);
-} clap_host_midi_mappings_t;
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/clap/ext/draft/param-indication.h b/include/clap/ext/draft/param-indication.h
@@ -1,73 +0,0 @@
-#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.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
diff --git a/include/clap/ext/draft/preset-load.h b/include/clap/ext/draft/preset-load.h
@@ -1,49 +0,0 @@
-#pragma once
-
-#include "../../plugin.h"
-
-static const char CLAP_EXT_PRESET_LOAD[] = "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
diff --git a/include/clap/ext/draft/remote-controls.h b/include/clap/ext/draft/remote-controls.h
@@ -1,79 +0,0 @@
-#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.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
diff --git a/include/clap/ext/draft/resource-directory.h b/include/clap/ext/draft/resource-directory.h
@@ -2,7 +2,7 @@
#include "../../plugin.h"
-static CLAP_CONSTEXPR const char CLAP_EXT_RESOURCE_DIRECTORY[] = "clap.resource-directory.draft/0";
+static CLAP_CONSTEXPR const char CLAP_EXT_RESOURCE_DIRECTORY[] = "clap.resource-directory/1";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/ext/draft/state-context.h b/include/clap/ext/draft/state-context.h
@@ -1,64 +0,0 @@
-#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.
-///
-/// 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 the plugin implements CLAP_EXT_STATE_CONTEXT then it is mandatory to also implement
-/// CLAP_EXT_STATE.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static CLAP_CONSTEXPR const char CLAP_EXT_STATE_CONTEXT[] = "clap.state-context.draft/1";
-
-enum clap_plugin_state_context_type {
- // suitable for duplicating a plugin instance
- CLAP_STATE_CONTEXT_FOR_DUPLICATE = 1,
-
- // suitable for loading a state as a preset
- CLAP_STATE_CONTEXT_FOR_PRESET = 2,
-};
-
-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
diff --git a/include/clap/ext/draft/surround.h b/include/clap/ext/draft/surround.h
@@ -1,83 +0,0 @@
-#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.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 Left
- CLAP_SURROUND_BR = 5, // Back Right
- CLAP_SURROUND_FLC = 6, // Front Left of Center
- CLAP_SURROUND_FRC = 7, // Front Right of Center
- CLAP_SURROUND_BC = 8, // Back Center
- CLAP_SURROUND_SL = 9, // Side Left
- CLAP_SURROUND_SR = 10, // Side Right
- CLAP_SURROUND_TC = 11, // Top Center
- CLAP_SURROUND_TFL = 12, // Front Left Height
- CLAP_SURROUND_TFC = 13, // Front Center Height
- CLAP_SURROUND_TFR = 14, // Front Right Height
- CLAP_SURROUND_TBL = 15, // Rear Left Height
- CLAP_SURROUND_TBC = 16, // Rear Center Height
- CLAP_SURROUND_TBR = 17, // Rear Right Height
-};
-
-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
diff --git a/include/clap/ext/draft/track-info.h b/include/clap/ext/draft/track-info.h
@@ -1,62 +0,0 @@
-#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.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
diff --git a/include/clap/ext/draft/transport-control.h b/include/clap/ext/draft/transport-control.h
@@ -6,7 +6,7 @@
// 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.draft/0";
+static CLAP_CONSTEXPR const char CLAP_EXT_TRANSPORT_CONTROL[] = "clap.transport-control/1";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/ext/draft/triggers.h b/include/clap/ext/draft/triggers.h
@@ -4,7 +4,7 @@
#include "../../events.h"
#include "../../string-sizes.h"
-static CLAP_CONSTEXPR const char CLAP_EXT_TRIGGERS[] = "clap.triggers.draft/0";
+static CLAP_CONSTEXPR const char CLAP_EXT_TRIGGERS[] = "clap.triggers/1";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/ext/draft/tuning.h b/include/clap/ext/draft/tuning.h
@@ -4,7 +4,7 @@
#include "../../events.h"
#include "../../string-sizes.h"
-static CLAP_CONSTEXPR const char CLAP_EXT_TUNING[] = "clap.tuning.draft/2";
+static CLAP_CONSTEXPR const char CLAP_EXT_TUNING[] = "clap.tuning/2";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/ext/latency.h b/include/clap/ext/latency.h
@@ -8,10 +8,9 @@ static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency";
extern "C" {
#endif
-// The audio ports scan has to be done while the plugin is deactivated.
typedef struct clap_plugin_latency {
// Returns the plugin latency in samples.
- // [main-thread]
+ // [main-thread & active]
uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin);
} clap_plugin_latency_t;
diff --git a/include/clap/ext/param-indication.h b/include/clap/ext/param-indication.h
@@ -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
diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h
@@ -12,7 +12,7 @@
/// 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.value().
+/// @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()
diff --git a/include/clap/ext/preset-load.h b/include/clap/ext/preset-load.h
@@ -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
diff --git a/include/clap/ext/remote-controls.h b/include/clap/ext/remote-controls.h
@@ -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
diff --git a/include/clap/ext/state-context.h b/include/clap/ext/state-context.h
@@ -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
diff --git a/include/clap/ext/state.h b/include/clap/ext/state.h
@@ -10,6 +10,10 @@
/// 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";
diff --git a/include/clap/ext/surround.h b/include/clap/ext/surround.h
@@ -0,0 +1,87 @@
+#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 Left
+ CLAP_SURROUND_BR = 5, // Back Right
+ CLAP_SURROUND_FLC = 6, // Front Left of Center
+ CLAP_SURROUND_FRC = 7, // Front Right of Center
+ CLAP_SURROUND_BC = 8, // Back Center
+ CLAP_SURROUND_SL = 9, // Side Left
+ CLAP_SURROUND_SR = 10, // Side Right
+ CLAP_SURROUND_TC = 11, // Top Center
+ CLAP_SURROUND_TFL = 12, // Front Left Height
+ CLAP_SURROUND_TFC = 13, // Front Center Height
+ CLAP_SURROUND_TFR = 14, // Front Right Height
+ CLAP_SURROUND_TBL = 15, // Rear Left Height
+ CLAP_SURROUND_TBC = 16, // Rear Center Height
+ CLAP_SURROUND_TBR = 17, // Rear Right Height
+};
+
+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
diff --git a/include/clap/ext/track-info.h b/include/clap/ext/track-info.h
@@ -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
diff --git a/include/clap/ext/voice-info.h b/include/clap/ext/voice-info.h
@@ -9,7 +9,7 @@
// - 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 const char CLAP_EXT_VOICE_INFO[] = "clap.voice-info";
+static CLAP_CONSTEXPR const char CLAP_EXT_VOICE_INFO[] = "clap.voice-info";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/factory/draft/plugin-invalidation.h b/include/clap/factory/draft/plugin-invalidation.h
@@ -6,7 +6,7 @@
// Use it to retrieve const clap_plugin_invalidation_factory_t* from
// clap_plugin_entry.get_factory()
static const CLAP_CONSTEXPR char CLAP_PLUGIN_INVALIDATION_FACTORY_ID[] =
- "clap.plugin-invalidation-factory/draft0";
+ "clap.plugin-invalidation-factory/1";
#ifdef __cplusplus
extern "C" {
diff --git a/include/clap/factory/draft/plugin-state-converter.h b/include/clap/factory/draft/plugin-state-converter.h
@@ -0,0 +1,99 @@
+#pragma once
+
+#include "../../id.h"
+#include "../../universal-plugin-id.h"
+#include "../../stream.h"
+#include "../../version.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct clap_plugin_state_converter_descriptor {
+ clap_version_t clap_version;
+
+ clap_universal_plugin_id_t src_plugin_id;
+ clap_universal_plugin_id_t dst_plugin_id;
+
+ const char *id; // eg: "com.u-he.diva-converter", mandatory
+ const char *name; // eg: "Diva Converter", mandatory
+ const char *vendor; // eg: "u-he"
+ const char *version; // eg: 1.1.5
+ const char *description; // eg: "Official state converter for u-he Diva."
+} clap_plugin_state_converter_descriptor_t;
+
+// This interface provides a mechanism for the host to convert a plugin state and its automation
+// points to a new plugin.
+//
+// This is useful to convert from one plugin ABI to another one.
+// This is also useful to offer an upgrade path: from EQ version 1 to EQ version 2.
+// This can also be used to convert the state of a plugin that isn't maintained anymore into
+// another plugin that would be similar.
+typedef struct clap_plugin_state_converter {
+ const clap_plugin_state_converter_descriptor_t *desc;
+
+ void *converter_data;
+
+ // Destroy the converter.
+ void (*destroy)(struct clap_plugin_state_converter *converter);
+
+ // Converts the input state to a state usable by the destination plugin.
+ //
+ // error_buffer is a place holder of error_buffer_size bytes for storing a null-terminated
+ // error message in case of failure, which can be displayed to the user.
+ //
+ // Returns true on success.
+ // [thread-safe]
+ bool (*convert_state)(struct clap_plugin_state_converter *converter,
+ const clap_istream_t *src,
+ const clap_ostream_t *dst,
+ char *error_buffer,
+ size_t error_buffer_size);
+
+ // Converts a normalized value.
+ // Returns true on success.
+ // [thread-safe]
+ bool (*convert_normalized_value)(struct clap_plugin_state_converter *converter,
+ clap_id src_param_id,
+ double src_normalized_value,
+ clap_id *dst_param_id,
+ double *dst_normalized_value);
+
+ // Converts a plain value.
+ // Returns true on success.
+ // [thread-safe]
+ bool (*convert_plain_value)(struct clap_plugin_state_converter *converter,
+ clap_id src_param_id,
+ double src_plain_value,
+ clap_id *dst_param_id,
+ double *dst_plain_value);
+} clap_plugin_state_converter_t;
+
+// Factory identifier
+static CLAP_CONSTEXPR const char CLAP_PLUGIN_STATE_CONVERTER_FACTORY_ID[] =
+ "clap.plugin-state-converter-factory/1";
+
+// List all the plugin state converters available in the current DSO.
+typedef struct clap_plugin_state_converter_factory {
+ // Get the number of converters.
+ // [thread-safe]
+ uint32_t (*count)(const struct clap_plugin_state_converter_factory *factory);
+
+ // Retrieves a plugin state converter descriptor by its index.
+ // Returns null in case of error.
+ // The descriptor must not be freed.
+ // [thread-safe]
+ const clap_plugin_state_converter_descriptor_t *(*get_descriptor)(
+ const struct clap_plugin_state_converter_factory *factory, uint32_t index);
+
+ // Create a plugin state converter by its converter_id.
+ // The returned pointer must be freed by calling converter->destroy(converter);
+ // Returns null in case of error.
+ // [thread-safe]
+ clap_plugin_state_converter_t *(*create)(
+ const struct clap_plugin_state_converter_factory *factory, const char *converter_id);
+} clap_plugin_state_converter_factory_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/clap/factory/draft/preset-discovery.h b/include/clap/factory/draft/preset-discovery.h
@@ -1,327 +0,0 @@
-/*
- Preset Discovery API.
-
- Preset Discovery enables a plug-in host to identify where presets are found, what
- extensions they have, which plug-ins they apply to, and other metadata associated with the
- presets so that they can be indexed and searched for quickly within the plug-in host's browser.
-
- This has a number of advantages for the user:
- - it allows them to browse for presets from one central location in a consistent way
- - the user can browse for presets without having to commit to a particular plug-in first
-
- The API works as follow to index presets and presets metadata:
- 1. clap_plugin_entry.get_factory(CLAP_PRESET_DISCOVERY_FACTORY_ID)
- 2. clap_preset_discovery_factory_t.create(...)
- 3. clap_preset_discovery_provider.init() (only necessary the first time, declarations
- can be cached)
- `-> clap_preset_discovery_indexer.declare_filetype()
- `-> clap_preset_discovery_indexer.declare_location()
- `-> clap_preset_discovery_indexer.declare_soundpack() (optional)
- `-> clap_preset_discovery_indexer.set_invalidation_watch_file() (optional)
- 4. crawl the given locations and monitor file system changes
- `-> clap_preset_discovery_indexer.get_metadata() for each presets files
-
- Then to load a preset, use ext/draft/preset-load.h.
- TODO: create a dedicated repo for other plugin abi preset-load extension.
-
- The design of this API deliberately does not define a fixed set tags or categories. It is the
- plug-in host's job to try to intelligently map the raw list of features that are found for a
- preset and to process this list to generate something that makes sense for the host's tagging and
- categorization system. The reason for this is to reduce the work for a plug-in developer to add
- Preset Discovery support for their existing preset file format and not have to be concerned with
- all the different hosts and how they want to receive the metadata.
-
- VERY IMPORTANT:
- - the whole indexing process has to be **fast**
- - clap_preset_provider->get_metadata() has to be fast and avoid unnecessary operations
- - the whole indexing process must not be interactive
- - don't show dialogs, windows, ...
- - don't ask for user input
-*/
-
-#pragma once
-
-#include "../../private/std.h"
-#include "../../private/macros.h"
-#include "../../version.h"
-
-// Use it to retrieve const clap_preset_discovery_factory_t* from
-// clap_plugin_entry.get_factory()
-static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID[] =
- "clap.preset-discovery-factory/draft-2";
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum clap_preset_discovery_location_kind {
- // The preset are located in a file on the OS filesystem.
- // The location is then a path which works with the OS file system functions (open, stat, ...)
- // So both '/' and '\' shall work on Windows as a separator.
- CLAP_PRESET_DISCOVERY_LOCATION_FILE = 0,
-
- // The preset is bundled within the plugin DSO itself.
- // The location must then be null, as the preset are within the plugin itself and then the plugin
- // will act as a preset container.
- CLAP_PRESET_DISCOVERY_LOCATION_PLUGIN = 1,
-};
-
-enum clap_preset_discovery_flags {
- // This is for factory or sound-pack presets.
- CLAP_PRESET_DISCOVERY_IS_FACTORY_CONTENT = 1 << 0,
-
- // This is for user presets.
- CLAP_PRESET_DISCOVERY_IS_USER_CONTENT = 1 << 1,
-
- // This location is meant for demo presets, those are preset which may trigger
- // some limitation in the plugin because they require additional features which the user
- // needs to purchase or the content itself needs to be bought and is only available in
- // demo mode.
- CLAP_PRESET_DISCOVERY_IS_DEMO_CONTENT = 1 << 2,
-
- // This preset is a user's favorite
- CLAP_PRESET_DISCOVERY_IS_FAVORITE = 1 << 3,
-};
-
-// TODO: move clap_timestamp_t, CLAP_TIMESTAMP_UNKNOWN and clap_plugin_id_t to parent files once we
-// settle with preset discovery
-
-// This type defines a timestamp: the number of seconds since UNIX EPOCH.
-// See C's time_t time(time_t *).
-typedef uint64_t clap_timestamp_t;
-
-// Value for unknown timestamp.
-static const clap_timestamp_t CLAP_TIMESTAMP_UNKNOWN = 0;
-
-// Pair of plugin ABI and plugin identifier
-typedef struct clap_plugin_id {
- // The plugin ABI name, in lowercase.
- // eg: "clap"
- const char *abi;
-
- // The plugin ID, for example "com.u-he.Diva".
- // If the ABI rely upon binary plugin ids, then they shall be hex encoded (lower case).
- const char *id;
-} clap_plugin_id_t;
-
-// Receiver that receives the metadata for a single preset file.
-// The host would define the various callbacks in this interface and the preset parser function
-// would then call them.
-//
-// This interface isn't thread-safe.
-typedef struct clap_preset_discovery_metadata_receiver {
- void *receiver_data; // reserved pointer for the metadata receiver
-
- // If there is an error reading metadata from a file this should be called with an error
- // message.
- // os_error: the operating system error, if applicable. If not applicable set it to a non-error
- // value, eg: 0 on unix and Windows.
- void(CLAP_ABI *on_error)(const struct clap_preset_discovery_metadata_receiver *receiver,
- int32_t os_error,
- const char *error_message);
-
- // This must be called for every preset in the file and before any preset metadata is
- // sent with the calls below.
- //
- // If the preset file is a preset container then name and load_key are mandatory, otherwise
- // they are optional.
- //
- // The load_key is a machine friendly string used to load the preset inside the container via a
- // the preset-load plug-in extension. The load_key can also just be the subpath if that's what
- // the plugin wants but it could also be some other unique id like a database primary key or a
- // binary offset. It's use is entirely up to the plug-in.
- //
- // If the function returns false, then the provider must stop calling back into the receiver.
- bool(CLAP_ABI *begin_preset)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *name,
- const char *load_key);
-
- // Adds a plug-in id that this preset can be used with.
- void(CLAP_ABI *add_plugin_id)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const clap_plugin_id_t *plugin_id);
-
- // Sets the sound pack to which the preset belongs to.
- void(CLAP_ABI *set_soundpack_id)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *soundpack_id);
-
- // Sets the flags, see clap_preset_discovery_flags.
- // If unset, they are then inherited from the location.
- void(CLAP_ABI *set_flags)(const struct clap_preset_discovery_metadata_receiver *receiver,
- uint32_t flags);
-
- // Adds a creator name for the preset.
- void(CLAP_ABI *add_creator)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *creator);
-
- // Sets a description of the preset.
- void(CLAP_ABI *set_description)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *description);
-
- // Sets the creation time and last modification time of the preset.
- // If one of the times isn't known, set it to CLAP_TIMESTAMP_UNKNOWN.
- // If this function is not called, then the indexer may look at the file's creation and
- // modification time.
- void(CLAP_ABI *set_timestamps)(const struct clap_preset_discovery_metadata_receiver *receiver,
- clap_timestamp_t creation_time,
- clap_timestamp_t modification_time);
-
- // Adds a feature to the preset.
- //
- // The feature string is arbitrary, it is the indexer's job to understand it and remap it to its
- // internal categorization and tagging system.
- //
- // However, the strings from plugin-features.h should be understood by the indexer and one of the
- // plugin category could be provided to determine if the preset will result into an audio-effect,
- // instrument, ...
- //
- // Examples:
- // kick, drum, tom, snare, clap, cymbal, bass, lead, metalic, hardsync, crossmod, acid,
- // distorted, drone, pad, dirty, etc...
- void(CLAP_ABI *add_feature)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *feature);
-
- // Adds extra information to the metadata.
- void(CLAP_ABI *add_extra_info)(const struct clap_preset_discovery_metadata_receiver *receiver,
- const char *key,
- const char *value);
-} clap_preset_discovery_metadata_receiver_t;
-
-typedef struct clap_preset_discovery_filetype {
- const char *name;
- const char *description; // optional
-
- // `.' isn't included in the string.
- // If empty or NULL then every file should be matched.
- const char *file_extension;
-} clap_preset_discovery_filetype_t;
-
-// Defines a place in which to search for presets
-typedef struct clap_preset_discovery_location {
- uint32_t flags; // see enum clap_preset_discovery_flags
- const char *name; // name of this location
- uint32_t kind; // See clap_preset_discovery_location_kind
-
- // Actual location in which to crawl presets.
- // For FILE kind, the location can be either a path to a directory or a file.
- // For PLUGIN kind, the location must be null.
- const char *location;
-} clap_preset_discovery_location_t;
-
-// Describes an installed sound pack.
-typedef struct clap_preset_discovery_soundpack {
- uint32_t flags; // see enum clap_preset_discovery_flags
- const char *id; // sound pack identifier
- const char *name; // name of this sound pack
- const char *description; // optional, reasonably short description of the sound pack
- const char *homepage_url; // optional, url to the pack's homepage
- const char *vendor; // optional, sound pack's vendor
- const char *image_path; // optional, an image on disk
- clap_timestamp_t release_timestamp; // release date, CLAP_TIMESTAMP_UNKNOWN if unavailable
-} clap_preset_discovery_soundpack_t;
-
-// Describes a preset provider
-typedef struct clap_preset_discovery_provider_descriptor {
- clap_version_t clap_version; // initialized to CLAP_VERSION
- const char *id; // see plugin.h for advice on how to choose a good identifier
- const char *name; // eg: "Diva's preset provider"
- const char *vendor; // optional, eg: u-he
-} clap_preset_discovery_provider_descriptor_t;
-
-// This interface isn't thread-safe.
-typedef struct clap_preset_discovery_provider {
- const clap_preset_discovery_provider_descriptor_t *desc;
-
- void *provider_data; // reserved pointer for the provider
-
- // Initialize the preset provider.
- // It should declare all its locations, filetypes and sound packs.
- // Returns false if initialization failed.
- bool(CLAP_ABI *init)(const struct clap_preset_discovery_provider *provider);
-
- // Destroys the preset provider
- void(CLAP_ABI *destroy)(const struct clap_preset_discovery_provider *provider);
-
- // reads metadata from the given file and passes them to the metadata receiver
- // Returns true on success.
- bool(CLAP_ABI *get_metadata)(const struct clap_preset_discovery_provider *provider,
- uint32_t location_kind,
- const char *location,
- const clap_preset_discovery_metadata_receiver_t *metadata_receiver);
-
- // Query an extension.
- // The returned pointer is owned by the provider.
- // It is forbidden to call it before provider->init().
- // You can call it within provider->init() call, and after.
- const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_provider *provider,
- const char *extension_id);
-} clap_preset_discovery_provider_t;
-
-// This interface isn't thread-safe
-typedef struct clap_preset_discovery_indexer {
- clap_version_t clap_version; // initialized to CLAP_VERSION
- const char *name; // eg: "Bitwig Studio"
- const char *vendor; // optional, eg: "Bitwig GmbH"
- const char *url; // optional, eg: "https://bitwig.com"
- const char *version; // optional, eg: "4.3", see plugin.h for advice on how to format the version
-
- void *indexer_data; // reserved pointer for the indexer
-
- // Declares a preset filetype.
- // Don't callback into the provider during this call.
- // Returns false if the filetype is invalid.
- bool(CLAP_ABI *declare_filetype)(const struct clap_preset_discovery_indexer *indexer,
- const clap_preset_discovery_filetype_t *filetype);
-
- // Declares a preset location.
- // Don't callback into the provider during this call.
- // Returns false if the location is invalid.
- bool(CLAP_ABI *declare_location)(const struct clap_preset_discovery_indexer *indexer,
- const clap_preset_discovery_location_t *location);
-
- // Declares a sound pack.
- // Don't callback into the provider during this call.
- // Returns false if the sound pack is invalid.
- bool(CLAP_ABI *declare_soundpack)(const struct clap_preset_discovery_indexer *indexer,
- const clap_preset_discovery_soundpack_t *soundpack);
-
- // Query an extension.
- // The returned pointer is owned by the indexer.
- // It is forbidden to call it before provider->init().
- // You can call it within provider->init() call, and after.
- const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_indexer *indexer,
- const char *extension_id);
-} clap_preset_discovery_indexer_t;
-
-// Every methods in this factory must be thread-safe.
-// It is encouraged to perform preset indexing in background threads, maybe even in background
-// process.
-//
-// The host may use clap_plugin_invalidation_factory to detect filesystem changes
-// which may change the factory's content.
-typedef struct clap_preset_discovery_factory {
- // Get the number of preset providers available.
- // [thread-safe]
- uint32_t(CLAP_ABI *count)(const struct clap_preset_discovery_factory *factory);
-
- // Retrieves a preset provider descriptor by its index.
- // Returns null in case of error.
- // The descriptor must not be freed.
- // [thread-safe]
- const clap_preset_discovery_provider_descriptor_t *(CLAP_ABI *get_descriptor)(
- const struct clap_preset_discovery_factory *factory, uint32_t index);
-
- // Create a preset provider by its id.
- // The returned pointer must be freed by calling preset_provider->destroy(preset_provider);
- // The preset provider is not allowed to use the indexer callbacks in the create method.
- // It is forbidden to call back into the indexer before the indexer calls provider->init().
- // Returns null in case of error.
- // [thread-safe]
- const clap_preset_discovery_provider_t *(CLAP_ABI *create)(
- const struct clap_preset_discovery_factory *factory,
- const clap_preset_discovery_indexer_t *indexer,
- const char *provider_id);
-} clap_preset_discovery_factory_t;
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/clap/factory/preset-discovery.h b/include/clap/factory/preset-discovery.h
@@ -0,0 +1,313 @@
+/*
+ Preset Discovery API.
+
+ Preset Discovery enables a plug-in host to identify where presets are found, what
+ extensions they have, which plug-ins they apply to, and other metadata associated with the
+ presets so that they can be indexed and searched for quickly within the plug-in host's browser.
+
+ This has a number of advantages for the user:
+ - it allows them to browse for presets from one central location in a consistent way
+ - the user can browse for presets without having to commit to a particular plug-in first
+
+ The API works as follow to index presets and presets metadata:
+ 1. clap_plugin_entry.get_factory(CLAP_PRESET_DISCOVERY_FACTORY_ID)
+ 2. clap_preset_discovery_factory_t.create(...)
+ 3. clap_preset_discovery_provider.init() (only necessary the first time, declarations
+ can be cached)
+ `-> clap_preset_discovery_indexer.declare_filetype()
+ `-> clap_preset_discovery_indexer.declare_location()
+ `-> clap_preset_discovery_indexer.declare_soundpack() (optional)
+ `-> clap_preset_discovery_indexer.set_invalidation_watch_file() (optional)
+ 4. crawl the given locations and monitor file system changes
+ `-> clap_preset_discovery_indexer.get_metadata() for each presets files
+
+ Then to load a preset, use ext/draft/preset-load.h.
+ TODO: create a dedicated repo for other plugin abi preset-load extension.
+
+ The design of this API deliberately does not define a fixed set tags or categories. It is the
+ plug-in host's job to try to intelligently map the raw list of features that are found for a
+ preset and to process this list to generate something that makes sense for the host's tagging and
+ categorization system. The reason for this is to reduce the work for a plug-in developer to add
+ Preset Discovery support for their existing preset file format and not have to be concerned with
+ all the different hosts and how they want to receive the metadata.
+
+ VERY IMPORTANT:
+ - the whole indexing process has to be **fast**
+ - clap_preset_provider->get_metadata() has to be fast and avoid unnecessary operations
+ - the whole indexing process must not be interactive
+ - don't show dialogs, windows, ...
+ - don't ask for user input
+*/
+
+#pragma once
+
+#include "../private/std.h"
+#include "../private/macros.h"
+#include "../timestamp.h"
+#include "../version.h"
+#include "../universal-plugin-id.h"
+
+// Use it to retrieve const clap_preset_discovery_factory_t* from
+// clap_plugin_entry.get_factory()
+static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID[] =
+ "clap.preset-discovery-factory/2";
+
+// The latest draft is 100% compatible.
+// This compat ID may be removed in 2026.
+static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID_COMPAT[] =
+ "clap.preset-discovery-factory/draft-2";
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum clap_preset_discovery_location_kind {
+ // The preset are located in a file on the OS filesystem.
+ // The location is then a path which works with the OS file system functions (open, stat, ...)
+ // So both '/' and '\' shall work on Windows as a separator.
+ CLAP_PRESET_DISCOVERY_LOCATION_FILE = 0,
+
+ // The preset is bundled within the plugin DSO itself.
+ // The location must then be null, as the preset are within the plugin itself and then the plugin
+ // will act as a preset container.
+ CLAP_PRESET_DISCOVERY_LOCATION_PLUGIN = 1,
+};
+
+enum clap_preset_discovery_flags {
+ // This is for factory or sound-pack presets.
+ CLAP_PRESET_DISCOVERY_IS_FACTORY_CONTENT = 1 << 0,
+
+ // This is for user presets.
+ CLAP_PRESET_DISCOVERY_IS_USER_CONTENT = 1 << 1,
+
+ // This location is meant for demo presets, those are preset which may trigger
+ // some limitation in the plugin because they require additional features which the user
+ // needs to purchase or the content itself needs to be bought and is only available in
+ // demo mode.
+ CLAP_PRESET_DISCOVERY_IS_DEMO_CONTENT = 1 << 2,
+
+ // This preset is a user's favorite
+ CLAP_PRESET_DISCOVERY_IS_FAVORITE = 1 << 3,
+};
+
+// Receiver that receives the metadata for a single preset file.
+// The host would define the various callbacks in this interface and the preset parser function
+// would then call them.
+//
+// This interface isn't thread-safe.
+typedef struct clap_preset_discovery_metadata_receiver {
+ void *receiver_data; // reserved pointer for the metadata receiver
+
+ // If there is an error reading metadata from a file this should be called with an error
+ // message.
+ // os_error: the operating system error, if applicable. If not applicable set it to a non-error
+ // value, eg: 0 on unix and Windows.
+ void(CLAP_ABI *on_error)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ int32_t os_error,
+ const char *error_message);
+
+ // This must be called for every preset in the file and before any preset metadata is
+ // sent with the calls below.
+ //
+ // If the preset file is a preset container then name and load_key are mandatory, otherwise
+ // they are optional.
+ //
+ // The load_key is a machine friendly string used to load the preset inside the container via a
+ // the preset-load plug-in extension. The load_key can also just be the subpath if that's what
+ // the plugin wants but it could also be some other unique id like a database primary key or a
+ // binary offset. It's use is entirely up to the plug-in.
+ //
+ // If the function returns false, then the provider must stop calling back into the receiver.
+ bool(CLAP_ABI *begin_preset)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *name,
+ const char *load_key);
+
+ // Adds a plug-in id that this preset can be used with.
+ void(CLAP_ABI *add_plugin_id)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const clap_universal_plugin_id_t *plugin_id);
+
+ // Sets the sound pack to which the preset belongs to.
+ void(CLAP_ABI *set_soundpack_id)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *soundpack_id);
+
+ // Sets the flags, see clap_preset_discovery_flags.
+ // If unset, they are then inherited from the location.
+ void(CLAP_ABI *set_flags)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ uint32_t flags);
+
+ // Adds a creator name for the preset.
+ void(CLAP_ABI *add_creator)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *creator);
+
+ // Sets a description of the preset.
+ void(CLAP_ABI *set_description)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *description);
+
+ // Sets the creation time and last modification time of the preset.
+ // If one of the times isn't known, set it to CLAP_TIMESTAMP_UNKNOWN.
+ // If this function is not called, then the indexer may look at the file's creation and
+ // modification time.
+ void(CLAP_ABI *set_timestamps)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ clap_timestamp creation_time,
+ clap_timestamp modification_time);
+
+ // Adds a feature to the preset.
+ //
+ // The feature string is arbitrary, it is the indexer's job to understand it and remap it to its
+ // internal categorization and tagging system.
+ //
+ // However, the strings from plugin-features.h should be understood by the indexer and one of the
+ // plugin category could be provided to determine if the preset will result into an audio-effect,
+ // instrument, ...
+ //
+ // Examples:
+ // kick, drum, tom, snare, clap, cymbal, bass, lead, metalic, hardsync, crossmod, acid,
+ // distorted, drone, pad, dirty, etc...
+ void(CLAP_ABI *add_feature)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *feature);
+
+ // Adds extra information to the metadata.
+ void(CLAP_ABI *add_extra_info)(const struct clap_preset_discovery_metadata_receiver *receiver,
+ const char *key,
+ const char *value);
+} clap_preset_discovery_metadata_receiver_t;
+
+typedef struct clap_preset_discovery_filetype {
+ const char *name;
+ const char *description; // optional
+
+ // `.' isn't included in the string.
+ // If empty or NULL then every file should be matched.
+ const char *file_extension;
+} clap_preset_discovery_filetype_t;
+
+// Defines a place in which to search for presets
+typedef struct clap_preset_discovery_location {
+ uint32_t flags; // see enum clap_preset_discovery_flags
+ const char *name; // name of this location
+ uint32_t kind; // See clap_preset_discovery_location_kind
+
+ // Actual location in which to crawl presets.
+ // For FILE kind, the location can be either a path to a directory or a file.
+ // For PLUGIN kind, the location must be null.
+ const char *location;
+} clap_preset_discovery_location_t;
+
+// Describes an installed sound pack.
+typedef struct clap_preset_discovery_soundpack {
+ uint32_t flags; // see enum clap_preset_discovery_flags
+ const char *id; // sound pack identifier
+ const char *name; // name of this sound pack
+ const char *description; // optional, reasonably short description of the sound pack
+ const char *homepage_url; // optional, url to the pack's homepage
+ const char *vendor; // optional, sound pack's vendor
+ const char *image_path; // optional, an image on disk
+ clap_timestamp release_timestamp; // release date, CLAP_TIMESTAMP_UNKNOWN if unavailable
+} clap_preset_discovery_soundpack_t;
+
+// Describes a preset provider
+typedef struct clap_preset_discovery_provider_descriptor {
+ clap_version_t clap_version; // initialized to CLAP_VERSION
+ const char *id; // see plugin.h for advice on how to choose a good identifier
+ const char *name; // eg: "Diva's preset provider"
+ const char *vendor; // optional, eg: u-he
+} clap_preset_discovery_provider_descriptor_t;
+
+// This interface isn't thread-safe.
+typedef struct clap_preset_discovery_provider {
+ const clap_preset_discovery_provider_descriptor_t *desc;
+
+ void *provider_data; // reserved pointer for the provider
+
+ // Initialize the preset provider.
+ // It should declare all its locations, filetypes and sound packs.
+ // Returns false if initialization failed.
+ bool(CLAP_ABI *init)(const struct clap_preset_discovery_provider *provider);
+
+ // Destroys the preset provider
+ void(CLAP_ABI *destroy)(const struct clap_preset_discovery_provider *provider);
+
+ // reads metadata from the given file and passes them to the metadata receiver
+ // Returns true on success.
+ bool(CLAP_ABI *get_metadata)(const struct clap_preset_discovery_provider *provider,
+ uint32_t location_kind,
+ const char *location,
+ const clap_preset_discovery_metadata_receiver_t *metadata_receiver);
+
+ // Query an extension.
+ // The returned pointer is owned by the provider.
+ // It is forbidden to call it before provider->init().
+ // You can call it within provider->init() call, and after.
+ const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_provider *provider,
+ const char *extension_id);
+} clap_preset_discovery_provider_t;
+
+// This interface isn't thread-safe
+typedef struct clap_preset_discovery_indexer {
+ clap_version_t clap_version; // initialized to CLAP_VERSION
+ const char *name; // eg: "Bitwig Studio"
+ const char *vendor; // optional, eg: "Bitwig GmbH"
+ const char *url; // optional, eg: "https://bitwig.com"
+ const char *version; // optional, eg: "4.3", see plugin.h for advice on how to format the version
+
+ void *indexer_data; // reserved pointer for the indexer
+
+ // Declares a preset filetype.
+ // Don't callback into the provider during this call.
+ // Returns false if the filetype is invalid.
+ bool(CLAP_ABI *declare_filetype)(const struct clap_preset_discovery_indexer *indexer,
+ const clap_preset_discovery_filetype_t *filetype);
+
+ // Declares a preset location.
+ // Don't callback into the provider during this call.
+ // Returns false if the location is invalid.
+ bool(CLAP_ABI *declare_location)(const struct clap_preset_discovery_indexer *indexer,
+ const clap_preset_discovery_location_t *location);
+
+ // Declares a sound pack.
+ // Don't callback into the provider during this call.
+ // Returns false if the sound pack is invalid.
+ bool(CLAP_ABI *declare_soundpack)(const struct clap_preset_discovery_indexer *indexer,
+ const clap_preset_discovery_soundpack_t *soundpack);
+
+ // Query an extension.
+ // The returned pointer is owned by the indexer.
+ // It is forbidden to call it before provider->init().
+ // You can call it within provider->init() call, and after.
+ const void *(CLAP_ABI *get_extension)(const struct clap_preset_discovery_indexer *indexer,
+ const char *extension_id);
+} clap_preset_discovery_indexer_t;
+
+// Every methods in this factory must be thread-safe.
+// It is encouraged to perform preset indexing in background threads, maybe even in background
+// process.
+//
+// The host may use clap_plugin_invalidation_factory to detect filesystem changes
+// which may change the factory's content.
+typedef struct clap_preset_discovery_factory {
+ // Get the number of preset providers available.
+ // [thread-safe]
+ uint32_t(CLAP_ABI *count)(const struct clap_preset_discovery_factory *factory);
+
+ // Retrieves a preset provider descriptor by its index.
+ // Returns null in case of error.
+ // The descriptor must not be freed.
+ // [thread-safe]
+ const clap_preset_discovery_provider_descriptor_t *(CLAP_ABI *get_descriptor)(
+ const struct clap_preset_discovery_factory *factory, uint32_t index);
+
+ // Create a preset provider by its id.
+ // The returned pointer must be freed by calling preset_provider->destroy(preset_provider);
+ // The preset provider is not allowed to use the indexer callbacks in the create method.
+ // It is forbidden to call back into the indexer before the indexer calls provider->init().
+ // Returns null in case of error.
+ // [thread-safe]
+ const clap_preset_discovery_provider_t *(CLAP_ABI *create)(
+ const struct clap_preset_discovery_factory *factory,
+ const clap_preset_discovery_indexer_t *indexer,
+ const char *provider_id);
+} clap_preset_discovery_factory_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/clap/plugin.h b/include/clap/plugin.h
@@ -46,6 +46,9 @@ typedef struct clap_plugin {
// Must be called after creating the plugin.
// If init returns false, the host must destroy the plugin instance.
// If init returns true, then the plugin is initialized and in the deactivated state.
+ // Unlike in `plugin-factory::create_plugin`, in init you have complete access to the host
+ // and host extensions, so clap related setup activities should be done here rather than in
+ // create_plugin.
// [main-thread]
bool(CLAP_ABI *init)(const struct clap_plugin *plugin);
@@ -60,21 +63,21 @@ 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.
// Returns true on success.
- // [main-thread & !active_state]
+ // [main-thread & !active]
bool(CLAP_ABI *activate)(const struct clap_plugin *plugin,
double sample_rate,
uint32_t min_frames_count,
uint32_t max_frames_count);
- // [main-thread & active_state]
+ // [main-thread & active]
void(CLAP_ABI *deactivate)(const struct clap_plugin *plugin);
// Call start processing before processing.
// Returns true on success.
- // [audio-thread & active_state & !processing_state]
+ // [audio-thread & active & !processing]
bool(CLAP_ABI *start_processing)(const struct clap_plugin *plugin);
// Call stop processing before sending the plugin to sleep.
- // [audio-thread & active_state & processing_state]
+ // [audio-thread & active & processing]
void(CLAP_ABI *stop_processing)(const struct clap_plugin *plugin);
// - Clears all buffers, performs a full reset of the processing state (filters, oscillators,
@@ -82,13 +85,13 @@ typedef struct clap_plugin {
// - The parameter's value remain unchanged.
// - clap_process.steady_time may jump backward.
//
- // [audio-thread & active_state]
+ // [audio-thread & active]
void(CLAP_ABI *reset)(const struct clap_plugin *plugin);
// process audio, events, ...
// All the pointers coming from clap_process_t and its nested attributes,
// are valid until process() returns.
- // [audio-thread & active_state & processing_state]
+ // [audio-thread & active & processing]
clap_process_status(CLAP_ABI *process)(const struct clap_plugin *plugin,
const clap_process_t *process);
diff --git a/include/clap/timestamp.h b/include/clap/timestamp.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "private/std.h"
+#include "private/macros.h"
+
+// This type defines a timestamp: the number of seconds since UNIX EPOCH.
+// See C's time_t time(time_t *).
+typedef uint64_t clap_timestamp;
+
+// Value for unknown timestamp.
+static const CLAP_CONSTEXPR clap_timestamp CLAP_TIMESTAMP_UNKNOWN = 0;
diff --git a/include/clap/universal-plugin-id.h b/include/clap/universal-plugin-id.h
@@ -0,0 +1,26 @@
+#pragma once
+
+// Pair of plugin ABI and plugin identifier.
+//
+// If you want to represent other formats please send us an update to the comment with the
+// name of the abi and the representation of the id.
+typedef struct clap_universal_plugin_id {
+ // The plugin ABI name, in lowercase and null-terminated.
+ // eg: "clap", "vst3", "vst2", "au", ...
+ const char *abi;
+
+ // The plugin ID, null-terminated and formatted as follows:
+ //
+ // CLAP: use the plugin id
+ // eg: "com.u-he.diva"
+ //
+ // AU: format the string like "type:subt:manu"
+ // eg: "aumu:SgXT:VmbA"
+ //
+ // VST2: print the id as a signed 32-bits integer
+ // eg: "-4382976"
+ //
+ // VST3: print the id as a standard UUID
+ // eg: "123e4567-e89b-12d3-a456-426614174000"
+ const char *id;
+} clap_universal_plugin_id_t;
diff --git a/include/clap/version.h b/include/clap/version.h
@@ -21,8 +21,8 @@ typedef struct clap_version {
#endif
#define CLAP_VERSION_MAJOR 1
-#define CLAP_VERSION_MINOR 1
-#define CLAP_VERSION_REVISION 10
+#define CLAP_VERSION_MINOR 2
+#define CLAP_VERSION_REVISION 0
#define CLAP_VERSION_INIT \
{ (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION }
diff --git a/src/main.c b/src/main.c
@@ -1,4 +1,4 @@
-#include <clap/clap.h>
+#include <clap/all.h>
// The purpose of this file is to check that all headers compile
int main(int argc, char **argv) {
diff --git a/src/main.cc b/src/main.cc
@@ -1,4 +1,4 @@
-#include <clap/clap.h>
+#include <clap/all.h>
// The purpose of this file is to check that all headers compile
diff --git a/src/plugin-template.c b/src/plugin-template.c
@@ -6,6 +6,12 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <assert.h>
+
+#if __STDC_VERSION__ >= 201112L && !defined (__STDC_NO_THREADS__) && defined (CLAP_HAS_THREADS_H)
+# define CLAP_HAS_THREAD
+# include <threads.h>
+#endif
#include <clap/clap.h>
@@ -357,15 +363,82 @@ static const clap_plugin_factory_t s_plugin_factory = {
////////////////
static bool entry_init(const char *plugin_path) {
- // called only once, and very first
+ // perform the plugin initialization
return true;
}
static void entry_deinit(void) {
- // called before unloading the DSO
+ // perform the plugin de-initialization
+}
+
+#ifdef CLAP_HAS_THREAD
+static mtx_t g_entry_lock;
+static once_flag g_entry_once = ONCE_FLAG_INIT;
+#endif
+
+static int g_entry_init_counter = 0;
+
+#ifdef CLAP_HAS_THREAD
+// Initializes the necessary mutex for the entry guard
+static void entry_init_guard_init(void) {
+ mtx_init(&g_entry_lock, mtx_plain);
+}
+#endif
+
+// Thread safe init counter
+static bool entry_init_guard(const char *plugin_path) {
+#ifdef CLAP_HAS_THREAD
+ call_once(&g_entry_once, entry_init_guard_init);
+
+ mtx_lock(&g_entry_lock);
+#endif
+
+ const int cnt = ++g_entry_init_counter;
+ assert(cnt > 0);
+
+ bool succeed = true;
+ if (cnt == 1) {
+ succeed = entry_init(plugin_path);
+ if (!succeed)
+ g_entry_init_counter = 0;
+ }
+
+#ifdef CLAP_HAS_THREAD
+ mtx_unlock(&g_entry_lock);
+#endif
+
+ return succeed;
+}
+
+// Thread safe deinit counter
+static void entry_deinit_guard(void) {
+#ifdef CLAP_HAS_THREAD
+ call_once(&g_entry_once, entry_init_guard_init);
+
+ mtx_lock(&g_entry_lock);
+#endif
+
+ const int cnt = --g_entry_init_counter;
+ assert(cnt > 0);
+
+ bool succeed = true;
+ if (cnt == 0)
+ entry_deinit();
+
+#ifdef CLAP_HAS_THREAD
+ mtx_unlock(&g_entry_lock);
+#endif
}
static const void *entry_get_factory(const char *factory_id) {
+#ifdef CLAP_HAS_THREAD
+ call_once(&g_entry_once, entry_init_guard_init);
+#endif
+
+ assert(g_entry_init_counter > 0);
+ if (g_entry_init_counter <= 0)
+ return NULL;
+
if (!strcmp(factory_id, CLAP_PLUGIN_FACTORY_ID))
return &s_plugin_factory;
return NULL;
@@ -374,7 +447,7 @@ static const void *entry_get_factory(const char *factory_id) {
// This symbol will be resolved by the host
CLAP_EXPORT const clap_plugin_entry_t clap_entry = {
.clap_version = CLAP_VERSION_INIT,
- .init = entry_init,
- .deinit = entry_deinit,
+ .init = entry_init_guard,
+ .deinit = entry_deinit_guard,
.get_factory = entry_get_factory,
};