From 0473fa2b5725df462e83f2de883cf5c6c600af04 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 30 Sep 2024 03:09:28 -0400 Subject: [PATCH 01/10] Add a description of the expectation of request_callback timing (#422) * Add a description of the expectation of request_callback timing Without making a requirement, indicate the intent of the timing. * Add an apostrophe * Add host can starve feedback from alex * more review feedback * notjusthosts --- include/clap/host.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/clap/host.h b/include/clap/host.h index ddfeb8e7..c154c822 100644 --- a/include/clap/host.h +++ b/include/clap/host.h @@ -35,6 +35,13 @@ typedef struct clap_host { void(CLAP_ABI *request_process)(const struct clap_host *host); // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. + // This callback should be called as soon as practicable, usually in the host application's next + // available main thread time slice. Typically callbacks occur within 33ms / 30hz. + // Despite this guidance, plugins should not make assumptions about the exactness of timing for + // a main thread callback, but hosts should endeavour to be prompt. For example, in high load + // situations the environment may starve the gui/main thread in favor of audio processing, + // leading to substantially longer latencies for the callback than the indicative times given + // here. // [thread-safe] void(CLAP_ABI *request_callback)(const struct clap_host *host); } clap_host_t; From 6f80a828618a60f665f18aecae4d0055a554e428 Mon Sep 17 00:00:00 2001 From: Javantea Date: Thu, 24 Oct 2024 13:31:21 -0700 Subject: [PATCH 02/10] Fix abort on delete plugin from track FX. --- src/plugin-template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin-template.c b/src/plugin-template.c index 8436815c..00f1ca3e 100644 --- a/src/plugin-template.c +++ b/src/plugin-template.c @@ -419,7 +419,7 @@ static void entry_deinit_guard(void) { #endif const int cnt = --g_entry_init_counter; - assert(cnt > 0); + assert(cnt >= 0); bool succeed = true; if (cnt == 0) From 851aa37d487d6914861e6b44bbc1f15218bd2775 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 30 Oct 2024 08:50:41 -0400 Subject: [PATCH 03/10] Document the special lifetime of clap_event_midi_sysex::buffer per conversation on discord, oct 29 --- include/clap/events.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/clap/events.h b/include/clap/events.h index a6e97513..198c7222 100644 --- a/include/clap/events.h +++ b/include/clap/events.h @@ -297,11 +297,27 @@ typedef struct clap_event_midi { uint8_t data[3]; } clap_event_midi_t; +// clap_event_midi_sysex contains a pointer to a sysex contents buffer. +// The lifetime of this buffer is (from host->plugin) only the process +// call in which the event is delivered or (from plugin->host) only the +// duration of a try_push call. +// +// Since `clap_output_events.try_push` requires hosts to make a copy of +// an event, host implementers receiving sysex messages from plugins need +// to take care to both copy the event (so header, size, etc...) but +// also memcpy the contents of the sysex pointer to host-owned memory, and +// not just copy the data pointer. +// +// Similarly plugins retaining the sysex outside the lifetime of a single +// process call must copy the sysex buffer to plugin-owned memory. +// +// As a consequence, the data structure pointed to by the sysex buffer +// must be contiguous and copyable with `memcpy` of `size` bytes. typedef struct clap_event_midi_sysex { clap_event_header_t header; uint16_t port_index; - const uint8_t *buffer; // midi buffer + const uint8_t *buffer; // midi buffer. See lifetime comment above. uint32_t size; } clap_event_midi_sysex_t; From 1492e9ee86e65e857a6e6b5802290db201a8304c Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 8 Oct 2024 11:52:53 -0700 Subject: [PATCH 04/10] draft scratch-memory extension --- include/clap/all.h | 1 + include/clap/ext/draft/scratch-memory.h | 90 +++++++++++++++++++++++++ include/clap/plugin.h | 1 + 3 files changed, 92 insertions(+) create mode 100644 include/clap/ext/draft/scratch-memory.h diff --git a/include/clap/all.h b/include/clap/all.h index 2ce982a5..bfda937b 100644 --- a/include/clap/all.h +++ b/include/clap/all.h @@ -11,3 +11,4 @@ #include "ext/draft/triggers.h" #include "ext/draft/tuning.h" #include "ext/draft/undo.h" +#include "ext/draft/scratch-memory.h" diff --git a/include/clap/ext/draft/scratch-memory.h b/include/clap/ext/draft/scratch-memory.h new file mode 100644 index 00000000..8beaa84a --- /dev/null +++ b/include/clap/ext/draft/scratch-memory.h @@ -0,0 +1,90 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets the plugin request "scratch" memory from the host. +// +// The scratch memory is thread-local, and can be accessed during +// `clap_plugin->process()` and `clap_plugin_thread_pool->exec()`; +// its content is not persistent between callbacks. +// +// The motivation for this extension is to allow the plugin host +// to "share" a single scratch buffer across multiple plugin +// instances. +// +// For example, imagine the host needs to process N plugins +// in sequence, and each plugin requires 10K of scratch memory. +// If each plugin pre-allocates its own scratch memory, then N * 10K +// of memory is being allocated in total. However, if each plugin +// requests 10K of scratch memory from the host, then the host can +// allocate a single 10K scratch buffer, and make it available to all +// plugins. +// +// This optimization may allow for reduced memory usage and improved +// CPU cache usage. + +static CLAP_CONSTEXPR const char CLAP_EXT_SCRATCH_MEMORY[] = "clap.scratch-memory/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host_scratch_memory { + // Asks the host to reserve scratch memory. + // + // The plugin may call this method multiple times (for + // example, gradually decreasing the amount of scratch + // being asked for until the host returns true), however, + // the plugin should avoid calling this method un-neccesarily + // since the host implementation may be relatively expensive. + // If the plugin calls `reserve()` multiple times, then the + // last call invalidates all previous calls. + // + // De-activating the plugin releases the scratch memory. + // + // `max_concurrency_hint` is an optional hint which indicates + // the maximum number of threads concurrently accessing the scratch memory. + // Set to 0 if unspecified. + // + // Returns true on success. + // + // [main-thread & being-activated] + bool(CLAP_ABI *reserve)(const clap_host_t *host, + uint32_t scratch_size_bytes, + uint32_t max_concurrency_hint); + + // Returns a pointer to the "thread-local" scratch memory. + // + // If the scratch memory wasn't successfully reserved, returns NULL. + // + // If the plugin crosses `max_concurrency_hint`, then the return value + // is either NULL or a valid scratch memory pointer. + // + // This method may only be called by the plugin from the audio thread, + // (i.e. during the process() or thread_pool.exec() callback), and + // the provided memory is only valid until the plugin returns from + // that callback. The plugin must not hold any references to data + // that lives in the scratch memory after returning from the callback, + // as that data will likely be over-written by another plugin using + // the same scratch memory. + // + // The provided memory is not initialized, and may have been used + // by other plugin instances, so the plugin must correctly initialize + // the memory when using it. + // + // The provided memory is owned by the host, so the plugin must not + // free the memory. + // + // If the plugin wants to share the same scratch memory pointer with + // many threads, it must access the the scratch at the beginning of the + // `process()` callback, cache the returned pointer before calling + // `clap_host_thread_pool->request_exec()` and clear the cached pointer + // before returning from `process()`. + // + // [audio-thread] + void *(CLAP_ABI *access)(const clap_host_t *host); +} clap_host_scratch_memory_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/clap/plugin.h b/include/clap/plugin.h index 7e83074b..0a239457 100644 --- a/include/clap/plugin.h +++ b/include/clap/plugin.h @@ -61,6 +61,7 @@ typedef struct clap_plugin { // In this call the plugin may allocate memory and prepare everything needed for the process // call. The process's sample rate will be constant and process's frame count will included in // the [min, max] range, which is bounded by [1, INT32_MAX]. + // In this call the plugin may call host-provided methods marked [being-activated]. // Once activated the latency and port configuration must remain constant, until deactivation. // Returns true on success. // [main-thread & !active] From bdb1be48e38a2f69a07b32a87dab9fdab1c0b749 Mon Sep 17 00:00:00 2001 From: Eva Date: Sat, 16 Nov 2024 18:13:44 -0500 Subject: [PATCH 05/10] remove erroneous comment in ambisonic.h comment refered to a previous version of the ambisonic extension. --- include/clap/ext/ambisonic.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/clap/ext/ambisonic.h b/include/clap/ext/ambisonic.h index c9775171..8889904b 100644 --- a/include/clap/ext/ambisonic.h +++ b/include/clap/ext/ambisonic.h @@ -43,9 +43,6 @@ typedef struct clap_plugin_ambisonic { 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, From 10210048c6189fa0841b2fd8e4e13b2071881375 Mon Sep 17 00:00:00 2001 From: Roelof van Krimpen Date: Mon, 22 Apr 2024 12:59:26 +0200 Subject: [PATCH 06/10] Draft location ext --- include/clap/all.h | 1 + include/clap/color.h | 2 + include/clap/ext/draft/location.h | 74 +++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 include/clap/ext/draft/location.h diff --git a/include/clap/all.h b/include/clap/all.h index bfda937b..54bbfbc4 100644 --- a/include/clap/all.h +++ b/include/clap/all.h @@ -9,6 +9,7 @@ #include "ext/draft/resource-directory.h" #include "ext/draft/transport-control.h" #include "ext/draft/triggers.h" +#include "ext/draft/location.h" #include "ext/draft/tuning.h" #include "ext/draft/undo.h" #include "ext/draft/scratch-memory.h" diff --git a/include/clap/color.h b/include/clap/color.h index 3f643590..9da24fac 100644 --- a/include/clap/color.h +++ b/include/clap/color.h @@ -13,6 +13,8 @@ typedef struct clap_color { uint8_t blue; } clap_color_t; +static const CLAP_CONSTEXPR clap_color_t CLAP_COLOR_TRANSPARENT = { 0, 0, 0, 0 }; + #ifdef __cplusplus } #endif diff --git a/include/clap/ext/draft/location.h b/include/clap/ext/draft/location.h new file mode 100644 index 00000000..3a44869f --- /dev/null +++ b/include/clap/ext/draft/location.h @@ -0,0 +1,74 @@ +#pragma once + +#include "../../color.h" +#include "../../plugin.h" +#include "../../string-sizes.h" + +// This extension allows a host to tell the plugin more about its position +// within a project or session. + +static CLAP_CONSTEXPR const char CLAP_EXT_LOCATION[] = "clap.location/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Represents a document/project/session. + CLAP_PLUGIN_LOCATION_PROJECT = 1, + + // Represents a group of tracks. + // It can contain track groups, tracks, and devices (post processing). + // The first device within a track group has the index of + // the last track or track group within this group + 1. + CLAP_PLUGIN_LOCATION_TRACK_GROUP = 2, + + // Represents a single track. + // It contains devices (serial). + CLAP_PLUGIN_LOCATION_TRACK = 3, + + // Represents a single device. + // It can contain other nested device chains. + CLAP_PLUGIN_LOCATION_DEVICE = 4, + + // Represents a nested device chain (serial). + // Its parent must be a device. + // It contains other devices. + CLAP_PLUGIN_LOCATION_NESTED_DEVICE_CHAIN = 5, +}; + +typedef struct clap_plugin_location_element { + // Kind of the element, must be one of the CLAP_PLUGIN_LOCATION_* values. + uint32_t kind; + + // Index within the parent element. + // Set to 0 if irrelevant. + uint32_t index; + + // Internal ID of the element. + // This is not intended for display to the user, + // but rather to give the host a potential quick way for lookups. + char id[CLAP_PATH_SIZE]; + + // User friendly name of the element. + char name[CLAP_NAME_SIZE]; + + // Color for this element, should be CLAP_COLOR_TRANSPARENT if no color is + // used for this element. + clap_color_t color; +} clap_plugin_location_element_t; + +typedef struct clap_plugin_location { + // Called by the host when the location of the plugin instance changes. + // + // The last item in this array always refers to the device itself, and as + // such is expected to be of kind CLAP_PLUGIN_LOCATION_DEVICE. + // [main-thread] + void(CLAP_ABI *set_location)(const clap_plugin_t *plugin, + const clap_plugin_location_element_t *path, + uint32_t num_elements); +} clap_plugin_location_t; + +#ifdef __cplusplus +} +#endif From bae987e6194d7ea48166e515e644a3658c3de0c0 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Mon, 18 Nov 2024 22:37:56 -0500 Subject: [PATCH 07/10] Add some of the feedback from the Auburn/DPlug port basically expand some comments around ranges, meaning, and so on. --- include/clap/events.h | 13 ++++++++++++- include/clap/ext/gui.h | 11 +++++++++-- include/clap/ext/params.h | 6 +++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/clap/events.h b/include/clap/events.h index 198c7222..efcc2abb 100644 --- a/include/clap/events.h +++ b/include/clap/events.h @@ -9,7 +9,12 @@ extern "C" { #endif // event header -// must be the first attribute of the event +// All clap events start with an event header to determine the overall +// size of the event and its type and space (a namespacing for types). +// clap_event objects are contiguous regions of memory which can be copied +// with a memcpy of `size` bytes starting at the top of the header. As +// such, be very careful when desiginig clap events with internal pointers +// and other non-value-types to consider the lifetime of those members. typedef struct clap_event_header { uint32_t size; // event size including this header, eg: sizeof (clap_event_note) uint32_t time; // sample offset within the buffer for this event @@ -266,6 +271,12 @@ enum clap_transport_flags { CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL = 1 << 7, }; +// clap_event_transport provides song position, tempo, and similar information +// from the host to the plugin. There are two ways a host communicates these values. +// In the `clap_process` structure sent to each processing block, the host must +// provide a transport structure which indicates the available information at the +// start of the block. If the host provides sample-accurate tempo or transport changes, +// it can also provide subsequent inter-block transport updates by delivering a new event. typedef struct clap_event_transport { clap_event_header_t header; diff --git a/include/clap/ext/gui.h b/include/clap/ext/gui.h index 7704da91..d8d76eeb 100644 --- a/include/clap/ext/gui.h +++ b/include/clap/ext/gui.h @@ -13,6 +13,9 @@ /// Embedding the window gives more control to the host, and feels more integrated. /// Floating window are sometimes the only option due to technical limitations. /// +/// The Embedding protocol is by far the most common, supported by all hosts to date, +/// and a plugin author should support at least that case. +/// /// Showing the GUI works as follow: /// 1. clap_plugin_gui->is_api_supported(), check what can work /// 2. clap_plugin_gui->create(), allocates gui resources @@ -85,7 +88,10 @@ typedef struct clap_gui_resize_hints { bool can_resize_horizontally; bool can_resize_vertically; - // only if can resize horizontally and vertically + // if both horizontal and vertical resize are available, do we preserve the + // aspect ratio, and if so, what is the width x height aspect ratio to preserve. + // These flags are unused if can_resize_horizontally or vertically are false, + // and ratios are unused if preserve is false. bool preserve_aspect_ratio; uint32_t aspect_ratio_width; uint32_t aspect_ratio_height; @@ -94,7 +100,8 @@ typedef struct clap_gui_resize_hints { // Size (width, height) is in pixels; the corresponding windowing system extension is // responsible for defining if it is physical pixels or logical pixels. typedef struct clap_plugin_gui { - // Returns true if the requested gui api is supported + // Returns true if the requested gui api is supported, either in floating (plugin-created) + // or non-floating (embedded) mode. // [main-thread] bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating); diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h index 33602634..2f857696 100644 --- a/include/clap/ext/params.h +++ b/include/clap/ext/params.h @@ -246,9 +246,9 @@ typedef struct clap_param_info { // '/' will be used as a separator to show a tree-like structure. char module[CLAP_PATH_SIZE]; - double min_value; // Minimum plain value - double max_value; // Maximum plain value - double default_value; // Default plain value + double min_value; // Minimum plain value. Must be finite (`std::isfinite` true) + double max_value; // Maximum plain value. Must be finite + double default_value; // Default plain value. Must be in [min, max] range. } clap_param_info_t; typedef struct clap_plugin_params { From e79e1e5a5bb90ec75da9e9631f40c287ffdbeb2c Mon Sep 17 00:00:00 2001 From: Eva Date: Wed, 18 Dec 2024 10:12:02 -0500 Subject: [PATCH 08/10] Update README.md added zig bindings to language bindings section. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a790e6bf..71affd68 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ and use to get a basic plugin experience: - [clap-sys](https://github.com/glowcoil/clap-sys), rust binding - [CLAP-for-Delphi](https://github.com/Bremmers/CLAP-for-Delphi), Delphi binding +- [clap-zig-bindings](https://sr.ht/~interpunct/clap-zig-bindings/), Zig bindings ## Artwork From 2132243c19174b1b454512302398f34a052384fd Mon Sep 17 00:00:00 2001 From: Alexandre Bique Date: Mon, 18 Nov 2024 18:43:04 +0100 Subject: [PATCH 09/10] Update ChangeLog --- ChangeLog.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index c47a37dd..b0d1d05d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,20 @@ +# Changes in 1.2.3 + +## New draft extensions + +* [scratch-memory](include/clap/ext/draft/scratch-memory.h): host provided scratch memory within the process call +* [location](include/clap/ext/draft/location.h): better info about the plugin location within the project + +## Documention + +* [events.h](include/clap/events.h): clarify sysex lifetime +* [host.h](include/clap/host.h): clarify `request_callback()` +* [ambisonic.h](include/clap/ext/ambisonic.h): remove bad comment + +## Fixes + +* [plugin-template.c](src/plugin-template.c): fix bad assertion + # Changes in 1.2.2 * [thread-check.h](include/clap/ext/thread-check.h): expand the thread-doc to clarify and expand realtime From c279d5a335aed89d80b7960616a8e9b1ad584312 Mon Sep 17 00:00:00 2001 From: Alexandre Bique Date: Mon, 18 Nov 2024 18:44:07 +0100 Subject: [PATCH 10/10] CLAP 1.2.3 --- include/clap/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clap/version.h b/include/clap/version.h index d11069c1..78ac8b8c 100644 --- a/include/clap/version.h +++ b/include/clap/version.h @@ -22,7 +22,7 @@ typedef struct clap_version { #define CLAP_VERSION_MAJOR 1 #define CLAP_VERSION_MINOR 2 -#define CLAP_VERSION_REVISION 2 +#define CLAP_VERSION_REVISION 3 #define CLAP_VERSION_INIT \ { (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION }