From a5aca003c823a3b27258ff320c118e3736cfd65f Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 8 Oct 2024 11:52:53 -0700 Subject: [PATCH 1/6] draft scratch-memory extension --- include/clap/ext/draft/scratch-memory.h | 91 +++++++++++++++++++++++++ include/clap/plugin.h | 1 + 2 files changed, 92 insertions(+) create mode 100644 include/clap/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..556e5eab --- /dev/null +++ b/include/clap/ext/draft/scratch-memory.h @@ -0,0 +1,91 @@ +#pragma once + +#include "../../plugin.h" + +// This extension lets the plugin request "scratch" memory +// from the host. Scratch memory can be accessed during the +// `process()` callback, but its content 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 three plugins +// in sequence, and each plugin requires 10K of scratch memory. +// If each plugin pre-allocates its own scratch memory, then 30K +// 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 +// three 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 for certain amount of scratch memory. + // If the host is unable to provide the memory, it should + // return "false". + // + // 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 + // final call determines the actual amount of scratch memory + // that will be available to the plugin. If the final call + // returns false then no scratch memory will be provided, + // regardless of any previous calls to `reserve()`. + // + // When the plugin is de-activated, the scratch memory + // is invalidated, and the host may free the memory if + // appropriate. The plugin will need to reserve scratch + // memory again the next time it is activated. + // + // In the context of plugins and hosts that implement + // the "thread-pool" extension, scratch memory is assumed + // to be "thread-local". The plugin should request the maximum + // amount of scratch memory that it will need on a single + // thread. Accordingly, the host must ensure that each + // thread can independently provide the requested amount + // of scratch memory. + // + // [main-thread & being-activated] + bool(CLAP_ABI *reserve)(const clap_host_t *host, uint32_t scratch_size_bytes); + + // Asks the host for the previously reserved scratch memory. + // If the host returned "true" when scratch memory was requested, + // then this method must return a pointer to a memory block at least + // as large as the reserved size. If the host returned "false" + // when scratch memory was requested, then this method must not + // be called, and will return NULL. + // + // 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 should not + // attempt to free the memory. + // + // [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 8d8d485445e2cb46970829e0d66bbfe8ea3e31d0 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 30 Oct 2024 08:50:41 -0400 Subject: [PATCH 2/6] 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 076ddda3243ef1ff36cc7d40d5ed82f439b03c52 Mon Sep 17 00:00:00 2001 From: trinitou Date: Fri, 1 Nov 2024 05:13:24 +0100 Subject: [PATCH 3/6] draft param-origin extension --- include/clap/ext/draft/param-origin.h | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 include/clap/ext/draft/param-origin.h diff --git a/include/clap/ext/draft/param-origin.h b/include/clap/ext/draft/param-origin.h new file mode 100644 index 00000000..d08edd27 --- /dev/null +++ b/include/clap/ext/draft/param-origin.h @@ -0,0 +1,61 @@ +#pragma once + +#include "../../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAM_ORIGIN[] = "clap.param-origin/1"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// This extension provides an optional value per parameter that lets the host draw a visual +/// indication for the parameter's origin. +/// +/// examples: +/// - lowpass filter cutoff parameter with an origin equal to param_info.min_value +/// [--------------> ] +/// 60Hz 20kHz +/// min=origin max +/// - highpass filter cutoff parameter with an origin equal to param_info.max_value +/// [ <--------------] +/// 60Hz 20kHz +/// min max=origin +/// - (bipolar) parameter with a range from -1.0 to +1.0 with an origin of 0.0 +/// [ <------| ] +/// -1.0 0.0 +1.0 +/// min origin max +/// - crossfade parameter without an origin +/// [ o ] +/// A B +/// min max + +typedef struct clap_plugin_param_origin { + // Get the origin value for a parameter. + // Returns false if the parameter has no origin, true otherwise. + // The host must not call this for params with CLAP_PARAM_IS_ENUM flag set. + // + // out_value constraints: + // - has to be in the range from param_info.min_value to param_info.max_value + // - has to be an integer value if CLAP_PARAM_IS_STEPPED flag is set + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, clap_id param_id, double *out_value); +} clap_plugin_param_origin_t; + +typedef struct clap_host_param_origin { + // Informs the host that param origins have changed. + // + // Note: If the plugin calls params.rescan with CLAP_PARAM_RESCAN_ALL, all previously scanned + // parameter origins must be considered invalid. It is thus not necessary for the plugin to call + // param_origin.changed in this case. + // + // Note: This is useful if a parameter origin changes on-the-fly. For example a plugin might want + // to change the origin of a filter cutoff frequency parameter when the corresponding filter type + // (LP/BP/HP) has changed. + // + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_param_origin_t; + +#ifdef __cplusplus +} +#endif From 614fc0df1aebc7f03de7975dc3dfbc8f06a00066 Mon Sep 17 00:00:00 2001 From: Roelof van Krimpen Date: Mon, 22 Apr 2024 12:59:26 +0200 Subject: [PATCH 4/6] Draft track-location --- include/clap/all.h | 1 + include/clap/ext/draft/location.h | 54 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 include/clap/ext/draft/location.h diff --git a/include/clap/all.h b/include/clap/all.h index 2ce982a5..9d4acb94 100644 --- a/include/clap/all.h +++ b/include/clap/all.h @@ -9,5 +9,6 @@ #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" diff --git a/include/clap/ext/draft/location.h b/include/clap/ext/draft/location.h new file mode 100644 index 00000000..9cc424dd --- /dev/null +++ b/include/clap/ext/draft/location.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../../plugin.h" +#include "../../color.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 { + CLAP_PLUGIN_LOCATION_PROJECT, + CLAP_PLUGIN_LOCATION_TRACK, + CLAP_PLUGIN_LOCATION_TRACK_GROUP, + CLAP_PLUGIN_LOCATION_DEVICE + CLAP_PLUGIN_LOCATION_DEVICE_PARALLEL_GROUP, + CLAP_PLUGIN_LOCATION_DEVICE_SERIAL_GROUP, +}; + +typedef struct clap_plugin_location_element { + // 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. + const char *id; + // User friendly name of the element. + const char *name; + // Kind of the element, must be one of the CLAP_PLUGIN_LOCATION_* values. + int kind; + // Index within the parent element. + uint32_t index_in_group; + // Index of the element in a global context. When sorting elements by this index, + // the order should mirror the order as it is displayed in the host. + uint32_t global_index; + // Color for this element, should be 0x00000000 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 (*set_location)(clap_plugin_t *plugin, clap_plugin_location_element_t *path, int num_elements); +} clap_plugin_location_t; + +#ifdef __cplusplus +} +#endif From d40e2837562e71deaeb7cb54abe21e197e5dfb40 Mon Sep 17 00:00:00 2001 From: Roelof van Krimpen Date: Fri, 1 Nov 2024 18:35:29 +0100 Subject: [PATCH 5/6] Fix missing comma --- include/clap/ext/draft/location.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/clap/ext/draft/location.h b/include/clap/ext/draft/location.h index 9cc424dd..30ec8f01 100644 --- a/include/clap/ext/draft/location.h +++ b/include/clap/ext/draft/location.h @@ -16,7 +16,7 @@ enum { CLAP_PLUGIN_LOCATION_PROJECT, CLAP_PLUGIN_LOCATION_TRACK, CLAP_PLUGIN_LOCATION_TRACK_GROUP, - CLAP_PLUGIN_LOCATION_DEVICE + CLAP_PLUGIN_LOCATION_DEVICE, CLAP_PLUGIN_LOCATION_DEVICE_PARALLEL_GROUP, CLAP_PLUGIN_LOCATION_DEVICE_SERIAL_GROUP, }; From 58660cb66f4081ba235922c71db34e66f507fa50 Mon Sep 17 00:00:00 2001 From: Roelof van Krimpen Date: Mon, 18 Nov 2024 09:39:08 +0100 Subject: [PATCH 6/6] Remove global index from clap_plugin_location_element_t, add constant for transparent color in color.h --- include/clap/color.h | 2 ++ include/clap/ext/draft/location.h | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) 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 index 30ec8f01..519c4e6c 100644 --- a/include/clap/ext/draft/location.h +++ b/include/clap/ext/draft/location.h @@ -31,11 +31,8 @@ typedef struct clap_plugin_location_element { int kind; // Index within the parent element. uint32_t index_in_group; - // Index of the element in a global context. When sorting elements by this index, - // the order should mirror the order as it is displayed in the host. - uint32_t global_index; - // Color for this element, should be 0x00000000 if no color is used for this - // element. + // 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;