commit 8db6c2f5fe0b42c5bf30f369ea5e62a623bb412b
parent 1bdbb7d9e13fc6e1f25506c127efa3cd48ec91ef
Author: falkTX <falktx@falktx.com>
Date: Wed, 12 Oct 2022 01:59:54 +0100
Update clap headers, add thread-check.h
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
16 files changed, 223 insertions(+), 96 deletions(-)
diff --git a/distrho/src/clap/entry.h b/distrho/src/clap/entry.h
@@ -48,16 +48,16 @@ typedef struct clap_plugin_entry {
//
// If init() returns false, then the host must not call deinit() nor any other clap
// related symbols from the DSO.
- bool (*init)(const char *plugin_path);
+ bool(CLAP_ABI *init)(const char *plugin_path);
// No more calls into the DSO must be made after calling deinit().
- void (*deinit)(void);
+ void(CLAP_ABI *deinit)(void);
// Get the pointer to a factory. See plugin-factory.h for an example.
//
// Returns null if the factory is not provided.
// The returned pointer must *not* be freed by the caller.
- const void *(*get_factory)(const char *factory_id);
+ const void *(CLAP_ABI *get_factory)(const char *factory_id);
} clap_plugin_entry_t;
/* Entry point */
diff --git a/distrho/src/clap/events.h b/distrho/src/clap/events.h
@@ -263,10 +263,11 @@ typedef struct clap_event_midi2 {
typedef struct clap_input_events {
void *ctx; // reserved pointer for the list
- uint32_t (*size)(const struct clap_input_events *list);
+ // returns the number of events in the list
+ uint32_t(CLAP_ABI *size)(const struct clap_input_events *list);
// Don't free the returned event, it belongs to the list
- const clap_event_header_t *(*get)(const struct clap_input_events *list, uint32_t index);
+ const clap_event_header_t *(CLAP_ABI *get)(const struct clap_input_events *list, uint32_t index);
} clap_input_events_t;
// Output event list, events must be sorted by time.
@@ -275,7 +276,8 @@ typedef struct clap_output_events {
// Pushes a copy of the event
// returns false if the event could not be pushed to the queue (out of memory?)
- bool (*try_push)(const struct clap_output_events *list, const clap_event_header_t *event);
+ bool(CLAP_ABI *try_push)(const struct clap_output_events *list,
+ const clap_event_header_t *event);
} clap_output_events_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/audio-ports.h b/distrho/src/clap/ext/audio-ports.h
@@ -69,14 +69,14 @@ typedef struct clap_audio_port_info {
typedef struct clap_plugin_audio_ports {
// number of ports, for either input or output
// [main-thread]
- uint32_t (*count)(const clap_plugin_t *plugin, bool is_input);
+ uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input);
// get info about about an audio port.
// [main-thread]
- bool (*get)(const clap_plugin_t *plugin,
- uint32_t index,
- bool is_input,
- clap_audio_port_info_t *info);
+ bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
+ uint32_t index,
+ bool is_input,
+ clap_audio_port_info_t *info);
} clap_plugin_audio_ports_t;
enum {
@@ -102,13 +102,13 @@ enum {
typedef struct clap_host_audio_ports {
// Checks if the host allows a plugin to change a given aspect of the audio ports definition.
// [main-thread]
- bool (*is_rescan_flag_supported)(const clap_host_t *host, uint32_t flag);
+ bool(CLAP_ABI *is_rescan_flag_supported)(const clap_host_t *host, uint32_t flag);
// Rescan the full list of audio ports according to the flags.
// It is illegal to ask the host to rescan with a flag that is not supported.
// Certain flags require the plugin to be de-activated.
// [main-thread]
- void (*rescan)(const clap_host_t *host, uint32_t flags);
+ void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags);
} clap_host_audio_ports_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/gui.h b/distrho/src/clap/ext/gui.h
@@ -97,12 +97,16 @@ typedef struct clap_gui_resize_hints {
typedef struct clap_plugin_gui {
// Returns true if the requested gui api is supported
// [main-thread]
- bool (*is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating);
+ bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating);
// Returns true if the plugin has a preferred api.
// The host has no obligation to honor the plugin preferrence, this is just a hint.
+ // The const char **api variable should be explicitly assigned as a pointer to
+ // one of the CLAP_WINDOW_API_ constants defined above, not strcopied.
// [main-thread]
- bool (*get_preferred_api)(const clap_plugin_t *plugin, const char **api, bool *is_floating);
+ bool(CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin,
+ const char **api,
+ bool *is_floating);
// Create and allocate all resources necessary for the gui.
//
@@ -115,11 +119,11 @@ typedef struct clap_plugin_gui {
//
// After this call, the GUI may not be visible yet; don't forget to call show().
// [main-thread]
- bool (*create)(const clap_plugin_t *plugin, const char *api, bool is_floating);
+ bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating);
// Free all resources associated with the gui.
// [main-thread]
- void (*destroy)(const clap_plugin_t *plugin);
+ void(CLAP_ABI *destroy)(const clap_plugin_t *plugin);
// Set the absolute GUI scaling factor, and override any OS info.
// Should not be used if the windowing api relies upon logical pixels.
@@ -130,21 +134,21 @@ typedef struct clap_plugin_gui {
// Returns true if the scaling could be applied
// Returns false if the call was ignored, or the scaling could not be applied.
// [main-thread]
- bool (*set_scale)(const clap_plugin_t *plugin, double scale);
+ bool(CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale);
// Get the current size of the plugin UI.
// clap_plugin_gui->create() must have been called prior to asking the size.
// [main-thread]
- bool (*get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
+ bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
// Returns true if the window is resizeable (mouse drag).
// Only for embedded windows.
// [main-thread]
- bool (*can_resize)(const clap_plugin_t *plugin);
+ bool(CLAP_ABI *can_resize)(const clap_plugin_t *plugin);
// Returns true if the plugin can provide hints on how to resize the window.
// [main-thread]
- bool (*get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints);
+ bool(CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints);
// If the plugin gui is resizable, then the plugin will calculate the closest
// usable size which fits in the given size.
@@ -152,38 +156,38 @@ typedef struct clap_plugin_gui {
//
// Only for embedded windows.
// [main-thread]
- bool (*adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
+ bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
// Sets the window size. Only for embedded windows.
// [main-thread]
- bool (*set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height);
+ bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height);
// Embbeds the plugin window into the given window.
// [main-thread & !floating]
- bool (*set_parent)(const clap_plugin_t *plugin, const clap_window_t *window);
+ bool(CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window);
// Set the plugin floating window to stay above the given window.
// [main-thread & floating]
- bool (*set_transient)(const clap_plugin_t *plugin, const clap_window_t *window);
+ bool(CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window);
// Suggests a window title. Only for floating windows.
// [main-thread & floating]
- void (*suggest_title)(const clap_plugin_t *plugin, const char *title);
+ void(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title);
// Show the window.
// [main-thread]
- bool (*show)(const clap_plugin_t *plugin);
+ bool(CLAP_ABI *show)(const clap_plugin_t *plugin);
// Hide the window, this method does not free the resources, it just hides
// the window content. Yet it may be a good idea to stop painting timers.
// [main-thread]
- bool (*hide)(const clap_plugin_t *plugin);
+ bool(CLAP_ABI *hide)(const clap_plugin_t *plugin);
} clap_plugin_gui_t;
typedef struct clap_host_gui {
// The host should call get_resize_hints() again.
// [thread-safe]
- void (*resize_hints_changed)(const clap_host_t *host);
+ void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host);
/* Request the host to resize the client area to width, height.
* Return true if the new size is accepted, false otherwise.
@@ -194,24 +198,24 @@ typedef struct clap_host_gui {
* satisfied then the host will call set_size() to revert the operation.
*
* [thread-safe] */
- bool (*request_resize)(const clap_host_t *host, uint32_t width, uint32_t height);
+ bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height);
/* Request the host to show the plugin gui.
* Return true on success, false otherwise.
* [thread-safe] */
- bool (*request_show)(const clap_host_t *host);
+ bool(CLAP_ABI *request_show)(const clap_host_t *host);
/* Request the host to hide the plugin gui.
* Return true on success, false otherwise.
* [thread-safe] */
- bool (*request_hide)(const clap_host_t *host);
+ bool(CLAP_ABI *request_hide)(const clap_host_t *host);
// The floating window has been closed, or the connection to the gui has been lost.
//
// If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge
// the gui destruction.
// [thread-safe]
- void (*closed)(const clap_host_t *host, bool was_destroyed);
+ void(CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed);
} clap_host_gui_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/latency.h b/distrho/src/clap/ext/latency.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "../plugin.h"
+
+static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency";
+
+#ifdef __cplusplus
+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.
+ // [main-thread]
+ uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin);
+} clap_plugin_latency_t;
+
+typedef struct clap_host_latency {
+ // Tell the host that the latency changed.
+ // The latency is only allowed to change if the plugin is deactivated.
+ // If the plugin is activated, call host->request_restart()
+ // [main-thread]
+ void(CLAP_ABI *changed)(const clap_host_t *host);
+} clap_host_latency_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/distrho/src/clap/ext/note-ports.h b/distrho/src/clap/ext/note-ports.h
@@ -42,14 +42,14 @@ typedef struct clap_note_port_info {
typedef struct clap_plugin_note_ports {
// number of ports, for either input or output
// [main-thread]
- uint32_t (*count)(const clap_plugin_t *plugin, bool is_input);
+ uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input);
// get info about about a note port.
// [main-thread]
- bool (*get)(const clap_plugin_t *plugin,
- uint32_t index,
- bool is_input,
- clap_note_port_info_t *info);
+ bool(CLAP_ABI *get)(const clap_plugin_t *plugin,
+ uint32_t index,
+ bool is_input,
+ clap_note_port_info_t *info);
} clap_plugin_note_ports_t;
enum {
@@ -66,11 +66,11 @@ enum {
typedef struct clap_host_note_ports {
// Query which dialects the host supports
// [main-thread]
- uint32_t (*supported_dialects)(const clap_host_t *host);
+ uint32_t(CLAP_ABI *supported_dialects)(const clap_host_t *host);
// Rescan the full list of note ports according to the flags.
// [main-thread]
- void (*rescan)(const clap_host_t *host, uint32_t flags);
+ void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags);
} clap_host_note_ports_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/params.h b/distrho/src/clap/ext/params.h
@@ -155,16 +155,43 @@ typedef struct clap_param_info {
clap_param_info_flags flags;
- // This value is optional and set by the plugin.
- // Its purpose is to provide a fast access to the plugin parameter:
+ // This value is optional and set by the plugin. The host will
+ // set it on all subsequent events regarding this param_id
+ // or set the cookie to nullptr if the host chooses to
+ // not implement cookies.
//
+ // The plugin must gracefully handle the case of a cookie
+ // which is nullptr, but can safely assume any cookie
+ // which is not nullptr is the value it issued.
+ //
+ // It is very strongly recommended that the host implement
+ // cookies. Some plugins may have noticably reduced
+ // performance when addressing params in hosts without cookies.
+ //
+ // The cookie's purpose is to provide a fast access to the
+ // plugin parameter objects. For instance:
+ //
+ // in clap_plugin_params.get_info
// Parameter *p = findParameter(param_id);
// param_info->cookie = p;
//
- // /* and later on */
- // Parameter *p = (Parameter *)cookie;
+ // later, in clap_plugin.process:
+ //
+ // Parameter *p{nullptr};
+ // if (evt->cookie) [[likely]]
+ // p = (Parameter *)evt->cookie;
+ // else
+ // p = -- alternate mechanism --
//
- // It is invalidated on clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) and when the plugin is
+ // where "alternate mechanism" is a mechanism the plugin implements
+ // to map parameter ids to internal objects.
+ //
+ // The host should make no assumption about the
+ // value of the cookie other than passing it back to the plugin or
+ // replacing it with nullptr.
+ //
+ // Once set, the cookie is valid until invalidated by a call to
+ // clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or when the plugin is
// destroyed.
void *cookie;
@@ -183,39 +210,44 @@ typedef struct clap_param_info {
typedef struct clap_plugin_params {
// Returns the number of parameters.
// [main-thread]
- uint32_t (*count)(const clap_plugin_t *plugin);
+ uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin);
// Copies the parameter's info to param_info and returns true on success.
// [main-thread]
- bool (*get_info)(const clap_plugin_t *plugin,
- uint32_t param_index,
- clap_param_info_t *param_info);
+ bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin,
+ uint32_t param_index,
+ clap_param_info_t *param_info);
// Gets the parameter plain value.
// [main-thread]
- bool (*get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value);
+ bool(CLAP_ABI *get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value);
// Formats the display text for the given parameter value.
// The host should always format the parameter value to text using this function
// before displaying it to the user.
// [main-thread]
- bool (*value_to_text)(
+ bool(CLAP_ABI *value_to_text)(
const clap_plugin_t *plugin, clap_id param_id, double value, char *display, uint32_t size);
// Converts the display text to a parameter value.
// [main-thread]
- bool (*text_to_value)(const clap_plugin_t *plugin,
- clap_id param_id,
- const char *display,
- double *value);
+ bool(CLAP_ABI *text_to_value)(const clap_plugin_t *plugin,
+ clap_id param_id,
+ const char *display,
+ double *value);
// Flushes a set of parameter changes.
// This method must not be called concurrently to clap_plugin->process().
//
+ // Note: if the plugin is processing, then the process() call will already achieve the
+ // parameter update (bi-directionnal), so a call to flush isn't required, also be aware
+ // that the plugin may use the sample offset in process(), while this information would be
+ // lost within flush().
+ //
// [active ? audio-thread : main-thread]
- void (*flush)(const clap_plugin_t *plugin,
- const clap_input_events_t *in,
- const clap_output_events_t *out);
+ void(CLAP_ABI *flush)(const clap_plugin_t *plugin,
+ const clap_input_events_t *in,
+ const clap_output_events_t *out);
} clap_plugin_params_t;
enum {
@@ -272,23 +304,23 @@ typedef uint32_t clap_param_clear_flags;
typedef struct clap_host_params {
// Rescan the full list of parameters according to the flags.
// [main-thread]
- void (*rescan)(const clap_host_t *host, clap_param_rescan_flags flags);
+ void(CLAP_ABI *rescan)(const clap_host_t *host, clap_param_rescan_flags flags);
// Clears references to a parameter.
// [main-thread]
- void (*clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags);
+ void(CLAP_ABI *clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags);
// Request a parameter flush.
//
// The host will then schedule a call to either:
// - clap_plugin.process()
- // - clap_plugin_params->flush()
+ // - clap_plugin_params.flush()
//
// This function is always safe to use and should not be called from an [audio-thread] as the
// plugin would already be within process() or flush().
//
// [thread-safe,!audio-thread]
- void (*request_flush)(const clap_host_t *host);
+ void(CLAP_ABI *request_flush)(const clap_host_t *host);
} clap_host_params_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/state.h b/distrho/src/clap/ext/state.h
@@ -13,19 +13,19 @@ typedef struct clap_plugin_state {
// Saves the plugin state into stream.
// Returns true if the state was correctly saved.
// [main-thread]
- bool (*save)(const clap_plugin_t *plugin, const clap_ostream_t *stream);
+ bool(CLAP_ABI *save)(const clap_plugin_t *plugin, const clap_ostream_t *stream);
// Loads the plugin state from stream.
// Returns true if the state was correctly restored.
// [main-thread]
- bool (*load)(const clap_plugin_t *plugin, const clap_istream_t *stream);
+ bool(CLAP_ABI *load)(const clap_plugin_t *plugin, const clap_istream_t *stream);
} clap_plugin_state_t;
typedef struct clap_host_state {
// Tell the host that the plugin state has changed and should be saved again.
// If a parameter value changes, then it is implicit that the state is dirty.
// [main-thread]
- void (*mark_dirty)(const clap_host_t *host);
+ void(CLAP_ABI *mark_dirty)(const clap_host_t *host);
} clap_host_state_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/ext/thread-check.h b/distrho/src/clap/ext/thread-check.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "../plugin.h"
+
+static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_CHECK[] = "clap.thread-check";
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @page thread-check
+///
+/// CLAP defines two symbolic threads:
+///
+/// main-thread:
+/// This is the thread in which most of the interaction between the plugin and host happens.
+/// It is usually the thread on which the GUI receives its events.
+/// It isn't a realtime thread, yet this thread needs to respond fast enough to user interaction,
+/// so it is recommended to run long and expensive tasks such as preset indexing or asset loading
+/// in dedicated background threads.
+///
+/// audio-thread:
+/// This thread is used for realtime audio processing. Its execution should be as deterministic
+/// as possible to meet the audio interface's deadline (can be <1ms). In other words, there is a
+/// known set of operations that should be avoided: malloc() and free(), mutexes (spin mutexes
+/// are worse), I/O, waiting, ...
+/// The audio-thread is something symbolic, there isn't one OS thread that remains the
+/// audio-thread for the plugin lifetime. As you may guess, the host is likely to have a
+/// thread pool and the plugin.process() call may be scheduled on different OS threads over time.
+/// The most important thing is that there can't be two audio-threads at the same time. All the
+/// functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread,
+/// including the main-thread as the audio-thread, as long as it can guarentee that only one OS
+/// thread is the audio-thread at a time. The audio-thread can be seen as a concurrency guard for
+/// all functions marked with [audio-thread].
+
+// This interface is useful to do runtime checks and make
+// sure that the functions are called on the correct threads.
+// It is highly recommended that hosts implement this extension.
+typedef struct clap_host_thread_check {
+ // Returns true if "this" thread is the main thread.
+ // [thread-safe]
+ bool(CLAP_ABI *is_main_thread)(const clap_host_t *host);
+
+ // Returns true if "this" thread is one of the audio threads.
+ // [thread-safe]
+ bool(CLAP_ABI *is_audio_thread)(const clap_host_t *host);
+} clap_host_thread_check_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/distrho/src/clap/ext/timer-support.h b/distrho/src/clap/ext/timer-support.h
@@ -10,7 +10,7 @@ extern "C" {
typedef struct clap_plugin_timer_support {
// [main-thread]
- void (*on_timer)(const clap_plugin_t *plugin, clap_id timer_id);
+ void(CLAP_ABI *on_timer)(const clap_plugin_t *plugin, clap_id timer_id);
} clap_plugin_timer_support_t;
typedef struct clap_host_timer_support {
@@ -18,10 +18,10 @@ typedef struct clap_host_timer_support {
// The host may adjust the period if it is under a certain threshold.
// 30 Hz should be allowed.
// [main-thread]
- bool (*register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id);
+ bool(CLAP_ABI *register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id);
// [main-thread]
- bool (*unregister_timer)(const clap_host_t *host, clap_id timer_id);
+ bool(CLAP_ABI *unregister_timer)(const clap_host_t *host, clap_id timer_id);
} clap_host_timer_support_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/host.h b/distrho/src/clap/host.h
@@ -19,21 +19,21 @@ typedef struct clap_host {
// Query an extension.
// [thread-safe]
- const void *(*get_extension)(const struct clap_host *host, const char *extension_id);
+ const void *(CLAP_ABI *get_extension)(const struct clap_host *host, const char *extension_id);
// Request the host to deactivate and then reactivate the plugin.
// The operation may be delayed by the host.
// [thread-safe]
- void (*request_restart)(const struct clap_host *host);
+ void(CLAP_ABI *request_restart)(const struct clap_host *host);
// Request the host to activate and start processing the plugin.
// This is useful if you have external IO and need to wake up the plugin from "sleep".
// [thread-safe]
- void (*request_process)(const struct clap_host *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.
// [thread-safe]
- void (*request_callback)(const struct clap_host *host);
+ void(CLAP_ABI *request_callback)(const struct clap_host *host);
} clap_host_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/plugin-factory.h b/distrho/src/clap/plugin-factory.h
@@ -11,17 +11,18 @@ extern "C" {
// Every method must be thread-safe.
// It is very important to be able to scan the plugin as quickly as possible.
//
-// If the content of the factory may change due to external events, like the user installed
+// The host may use clap_plugin_invalidation_factory to detect filesystem changes
+// which may change the factory's content.
typedef struct clap_plugin_factory {
// Get the number of plugins available.
// [thread-safe]
- uint32_t (*get_plugin_count)(const struct clap_plugin_factory *factory);
+ uint32_t(CLAP_ABI *get_plugin_count)(const struct clap_plugin_factory *factory);
// Retrieves a plugin descriptor by its index.
// Returns null in case of error.
// The descriptor must not be freed.
// [thread-safe]
- const clap_plugin_descriptor_t *(*get_plugin_descriptor)(
+ const clap_plugin_descriptor_t *(CLAP_ABI *get_plugin_descriptor)(
const struct clap_plugin_factory *factory, uint32_t index);
// Create a clap_plugin by its plugin_id.
@@ -29,9 +30,9 @@ typedef struct clap_plugin_factory {
// The plugin is not allowed to use the host callbacks in the create method.
// Returns null in case of error.
// [thread-safe]
- const clap_plugin_t *(*create_plugin)(const struct clap_plugin_factory *factory,
- const clap_host_t *host,
- const char *plugin_id);
+ const clap_plugin_t *(CLAP_ABI *create_plugin)(const struct clap_plugin_factory *factory,
+ const clap_host_t *host,
+ const char *plugin_id);
} clap_plugin_factory_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/plugin.h b/distrho/src/clap/plugin.h
@@ -38,12 +38,12 @@ typedef struct clap_plugin {
// Must be called after creating the plugin.
// If init returns false, the host must destroy the plugin instance.
// [main-thread]
- bool (*init)(const struct clap_plugin *plugin);
+ bool(CLAP_ABI *init)(const struct clap_plugin *plugin);
// Free the plugin and its resources.
// It is required to deactivate the plugin prior to this call.
// [main-thread & !active]
- void (*destroy)(const struct clap_plugin *plugin);
+ void(CLAP_ABI *destroy)(const struct clap_plugin *plugin);
// Activate and deactivate the plugin.
// In this call the plugin may allocate memory and prepare everything needed for the process
@@ -52,21 +52,20 @@ typedef struct clap_plugin {
// Once activated the latency and port configuration must remain constant, until deactivation.
//
// [main-thread & !active_state]
- bool (*activate)(const struct clap_plugin *plugin,
- double sample_rate,
- uint32_t min_frames_count,
- uint32_t max_frames_count);
-
+ 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]
- void (*deactivate)(const struct clap_plugin *plugin);
+ void(CLAP_ABI *deactivate)(const struct clap_plugin *plugin);
// Call start processing before processing.
// [audio-thread & active_state & !processing_state]
- bool (*start_processing)(const struct clap_plugin *plugin);
+ 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]
- void (*stop_processing)(const struct clap_plugin *plugin);
+ void(CLAP_ABI *stop_processing)(const struct clap_plugin *plugin);
// - Clears all buffers, performs a full reset of the processing state (filters, oscillators,
// enveloppes, lfo, ...) and kills all voices.
@@ -74,21 +73,22 @@ typedef struct clap_plugin {
// - clap_process.steady_time may jump backward.
//
// [audio-thread & active_state]
- void (*reset)(const struct clap_plugin *plugin);
+ void(CLAP_ABI *reset)(const struct clap_plugin *plugin);
// process audio, events, ...
// [audio-thread & active_state & processing_state]
- clap_process_status (*process)(const struct clap_plugin *plugin, const clap_process_t *process);
+ clap_process_status(CLAP_ABI *process)(const struct clap_plugin *plugin,
+ const clap_process_t *process);
// Query an extension.
// The returned pointer is owned by the plugin.
// [thread-safe]
- const void *(*get_extension)(const struct clap_plugin *plugin, const char *id);
+ const void *(CLAP_ABI *get_extension)(const struct clap_plugin *plugin, const char *id);
// Called by the host on the main thread in response to a previous call to:
// host->request_callback(host);
// [main-thread]
- void (*on_main_thread)(const struct clap_plugin *plugin);
+ void(CLAP_ABI *on_main_thread)(const struct clap_plugin *plugin);
} clap_plugin_t;
#ifdef __cplusplus
diff --git a/distrho/src/clap/private/macros.h b/distrho/src/clap/private/macros.h
@@ -17,6 +17,14 @@
# endif
#endif
+#if !defined(CLAP_ABI)
+# if defined _WIN32 || defined __CYGWIN__
+# define CLAP_ABI __cdecl
+# else
+# define CLAP_ABI
+# endif
+#endif
+
#if defined(__cplusplus) && __cplusplus >= 201103L
# define CLAP_HAS_CXX11
# define CLAP_CONSTEXPR constexpr
diff --git a/distrho/src/clap/process.h b/distrho/src/clap/process.h
@@ -45,8 +45,9 @@ typedef struct clap_process {
const clap_event_transport_t *transport;
// Audio buffers, they must have the same count as specified
- // by clap_plugin_audio_ports->get_count().
- // The index maps to clap_plugin_audio_ports->get_info().
+ // by clap_plugin_audio_ports->count().
+ // The index maps to clap_plugin_audio_ports->get().
+ // Input buffer and its contents are read-only.
const clap_audio_buffer_t *audio_inputs;
clap_audio_buffer_t *audio_outputs;
uint32_t audio_inputs_count;
diff --git a/distrho/src/clap/stream.h b/distrho/src/clap/stream.h
@@ -11,14 +11,14 @@ typedef struct clap_istream {
void *ctx; // reserved pointer for the stream
// returns the number of bytes read; 0 indicates end of file and -1 a read error
- int64_t (*read)(const struct clap_istream *stream, void *buffer, uint64_t size);
+ int64_t(CLAP_ABI *read)(const struct clap_istream *stream, void *buffer, uint64_t size);
} clap_istream_t;
typedef struct clap_ostream {
void *ctx; // reserved pointer for the stream
// returns the number of bytes written; -1 on write error
- int64_t (*write)(const struct clap_ostream *stream, const void *buffer, uint64_t size);
+ int64_t(CLAP_ABI *write)(const struct clap_ostream *stream, const void *buffer, uint64_t size);
} clap_ostream_t;
#ifdef __cplusplus