diff --git a/ChangeLog.md b/ChangeLog.md index 0fa80c24..cfd44bcd 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,26 @@ +# Changes in 1.1.8 + +* [params.h](include/clap/ext/params.h): document how persisting parameter values between sessions should be implemented +* [state.h](include/clap/ext/state.h): add basic documentation regarding what state should be saved and how plugins should interact with buffers +* various documentation fixes (essentially typos) + +## Draft extensions + +* [extensible-audio-ports.h](include/clap/ext/draft/extensible-audio-ports.h): new extension which lets the host add ports to a plugin +* [configurable-audio-ports.h](include/clap/ext/draft/configurable-audio-ports.h): new extension allowing the host to **push** an audio ports configuration request, resulting in a simpler workflow for surround host and plugins +* [surround.h](include/clap/ext/draft/surround.h): + * remove `get_preferred_channel_map()` in favor of the push approach via [configurable-audio-ports.h](include/clap/ext/draft/configurable-audio-ports.h) + * remove `config_id` argument from `get_info()` +* [ambisonic.h](include/clap/ext/draft/ambisonic.h): remove `config_id` argument from `get_info()` +* [preset-load.h](include/clap/ext/draft/preset-load.h): use a location_kind + location approach instead of URI + +## Draft factories + +* [preset-discovery.h](include/clap/factory/draft/preset-discovery.h): + * use a location_kind + location approach instead of URI + * document which descriptor fields are optional + * allow optional preset names in the metadata for non-container presets + # Changes in 1.1.7 * Add a [factory](include/clap/factory) folder for better organization and move our factories there diff --git a/include/clap/clap.h b/include/clap/clap.h index 107ea376..e57dbf44 100644 --- a/include/clap/clap.h +++ b/include/clap/clap.h @@ -67,3 +67,5 @@ #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/events.h b/include/clap/events.h index 88cd5183..3a587bec 100644 --- a/include/clap/events.h +++ b/include/clap/events.h @@ -54,8 +54,8 @@ enum { // cases: // - a plugin is inside a drum pad in Bitwig Studio's drum machine, and this pad is choked by // another one - // - the user double clicks the DAW's stop button in the transport which then stops the sound on - // every tracks + // - the user double-clicks the DAW's stop button in the transport which then stops the sound on + // every track // // NOTE_END is sent by the plugin to the host. The port, channel, key and note_id are those given // by the host in the NOTE_ON event. In other words, this event is matched against the @@ -221,7 +221,7 @@ typedef struct clap_event_transport { clap_sectime song_pos_seconds; // position in seconds double tempo; // in bpm - double tempo_inc; // tempo increment for each samples and until the next + double tempo_inc; // tempo increment for each sample and until the next // time info event clap_beattime loop_start_beats; @@ -260,7 +260,7 @@ typedef struct clap_event_midi2 { uint32_t data[4]; } clap_event_midi2_t; -// Input event list, events must be sorted by time. +// Input event list. The host will deliver these sorted in sample order. typedef struct clap_input_events { void *ctx; // reserved pointer for the list @@ -271,7 +271,7 @@ typedef struct clap_input_events { 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. +// Output event list. The plugin must insert events in sample sorted order when inserting events typedef struct clap_output_events { void *ctx; // reserved pointer for the list diff --git a/include/clap/ext/audio-ports-config.h b/include/clap/ext/audio-ports-config.h index edad3294..6af65942 100644 --- a/include/clap/ext/audio-ports-config.h +++ b/include/clap/ext/audio-ports-config.h @@ -6,8 +6,8 @@ /// @page Audio Ports Config /// -/// This extension provides a way for the plugin to describe possible port configurations, for -/// example mono, stereo, surround, ... and a way for the host to select a configuration. +/// This extension let the plugin provide port configurations presets. +/// For example mono, stereo, surround, ambisonic, ... /// /// After the plugin initialization, the host may scan the list of configurations and eventually /// select one that fits the plugin context. The host can only select a configuration if the plugin @@ -80,7 +80,7 @@ typedef struct clap_plugin_audio_ports_config_info { // [main-thread] clap_id(CLAP_ABI *current_config)(const clap_plugin_t *plugin); - // Get info about about an audio port, for a given config_id. + // Get info about an audio port, for a given config_id. // This is analogous to clap_plugin_audio_ports.get(). // [main-thread] bool(CLAP_ABI *get)(const clap_plugin_t *plugin, diff --git a/include/clap/ext/draft/ambisonic.h b/include/clap/ext/draft/ambisonic.h index 7521a6d5..285a2979 100644 --- a/include/clap/ext/draft/ambisonic.h +++ b/include/clap/ext/draft/ambisonic.h @@ -4,7 +4,7 @@ // 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/1"; +static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC[] = "clap.ambisonic.draft/2"; static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic"; @@ -40,7 +40,6 @@ typedef struct clap_plugin_ambisonic { // If config_id is CLAP_INVALID_ID, then this function queries the current port info. // [main-thread] bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, - clap_id config_id, bool is_input, uint32_t port_index, clap_ambisonic_info_t *info); diff --git a/include/clap/ext/draft/configurable-audio-ports.h b/include/clap/ext/draft/configurable-audio-ports.h new file mode 100644 index 00000000..57de8057 --- /dev/null +++ b/include/clap/ext/draft/configurable-audio-ports.h @@ -0,0 +1,58 @@ +#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.draft0"; + +typedef struct clap_audio_port_configuration_request { + // When true, allows the plugin to pick a similar port configuration instead + // if the requested one can't be applied. + bool is_best_effort; + + // 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_info_t *info + const void *port_details; +} clap_audio_port_configuration_request_t; + +typedef struct clap_plugin_configurable_audio_ports { + // Some ports may not be configurable, or simply the result of another port configuration. + // For example if you have a simple delay plugin, then the output port must have the exact + // same type as the input port; in that example, we consider the output port type to be a + // function (identity) of the input port type. + // [main-thread && !active] + bool(CLAP_ABI *is_port_configurable)(const clap_plugin_t *plugin, + bool is_input, + uint32_t port_index); + + // Submit a bunch of configuration requests which will atomically be applied together, + // or discarded together. + // [main-thread && !active] + bool(CLAP_ABI *request_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 index 9e4ed84b..7e867afd 100644 --- a/include/clap/ext/draft/context-menu.h +++ b/include/clap/ext/draft/context-menu.h @@ -136,7 +136,7 @@ typedef struct clap_host_context_menu { clap_id action_id); // Returns true if the host can display a popup menu for the plugin. - // This may depends upon the current windowing system used to display the plugin, so the + // 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); diff --git a/include/clap/ext/draft/extensible-audio-ports.h b/include/clap/ext/draft/extensible-audio-ports.h new file mode 100644 index 00000000..278594b5 --- /dev/null +++ b/include/clap/ext/draft/extensible-audio-ports.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../audio-ports.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 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"; + +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. + // port_type: see clap_audio_port_info.port_type for interpretation. + // port_details: see clap_audio_port_configuration_request.port_details for interpretation. + // Returns true on success. + // [main-thread && !is_active] + bool(CLAP_ABI *add_port)(const clap_plugin_t *plugin, + bool is_input, + uint32_t channel_count, + const char *port_type, + const void *port_details); + + // Asks the plugin to remove a port. + // Returns true on success. + // [main-thread && !is_active] + bool(CLAP_ABI *remove_port)(const clap_plugin_t *plugin, bool is_input, uint32_t index); +} clap_plugin_extensible_audio_ports_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/clap/ext/draft/param-indication.h b/include/clap/ext/draft/param-indication.h index cc170fa4..5ec45f75 100644 --- a/include/clap/ext/draft/param-indication.h +++ b/include/clap/ext/draft/param-indication.h @@ -32,7 +32,7 @@ enum { // 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 ajust this + // 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, }; diff --git a/include/clap/ext/draft/preset-load.h b/include/clap/ext/draft/preset-load.h index 3653dd6b..44ad0cc2 100644 --- a/include/clap/ext/draft/preset-load.h +++ b/include/clap/ext/draft/preset-load.h @@ -2,21 +2,21 @@ #include "../../plugin.h" -static const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load.draft/1"; +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 URI. eg: - // - "file:///home/abique/.u-he/Diva/Presets/Diva/HS Bass Nine.h2p", load_key: null - // - "plugin://", load_key: - // - // The preset discovery provider defines the uri and load_key to be passed to this function. + // 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. // // [main-thread] - bool(CLAP_ABI *from_uri)(const clap_plugin_t *plugin, const char *uri, const char *load_key); + 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 { @@ -26,7 +26,9 @@ typedef struct clap_host_preset_load { // // [main-thread] void(CLAP_ABI *on_error)(const clap_host_t *host, - const char *uri, + uint32_t location_kind, + const char *location, + const char *load_key, int32_t os_error, const char *msg); @@ -36,7 +38,10 @@ typedef struct clap_host_preset_load { // must be null. // // [main-thread] - void(CLAP_ABI *loaded)(const clap_host_t *host, const char *uri, const char *load_key); + 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 diff --git a/include/clap/ext/draft/remote-controls.h b/include/clap/ext/draft/remote-controls.h index 0ff6b292..c5666ce7 100644 --- a/include/clap/ext/draft/remote-controls.h +++ b/include/clap/ext/draft/remote-controls.h @@ -67,7 +67,7 @@ typedef struct clap_host_remote_controls { // [main-thread] void(CLAP_ABI *changed)(const clap_host_t *host); - // Suggest a page to the host because it correspond to what the user is currently editing in the + // 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); diff --git a/include/clap/ext/draft/resource-directory.h b/include/clap/ext/draft/resource-directory.h index 514c671c..1d96da5f 100644 --- a/include/clap/ext/draft/resource-directory.h +++ b/include/clap/ext/draft/resource-directory.h @@ -24,7 +24,7 @@ extern "C" { /// -> suitable for read-write content /// /// Keeping the shared directory clean: -/// - to avoid clashes in the shared directory, plugins are encourraged to organize their files in +/// - to avoid clashes in the shared directory, plugins are encouraged to organize their files in /// sub-folders, for example create one subdirectory using the vendor name /// - don't use symbolic links or hard links which points outside of the directory /// @@ -35,7 +35,7 @@ extern "C" { /// are removed from the project /// /// Note for the host -/// - try to use the filesytem's copy-on-write feature when possible for reducing exclusive folder +/// - try to use the filesystem's copy-on-write feature when possible for reducing exclusive folder /// space usage on duplication /// - host can "garbage collect" the files in the shared folder using: /// clap_plugin_resource_directory.get_files_count() @@ -50,7 +50,7 @@ typedef struct clap_plugin_resource_directory { // [main-thread] void(CLAP_ABI *set_directory)(const clap_plugin_t *plugin, const char *path, bool is_shared); - // Asks the plugin to put its resources into the resources directory. + // Asks the plugin to put its resources into the resource directory. // It is not necessary to collect files which belongs to the plugin's // factory content unless the param all is true. // [main-thread] @@ -60,7 +60,7 @@ typedef struct clap_plugin_resource_directory { // [main-thread] uint32_t(CLAP_ABI *get_files_count)(const clap_plugin_t *plugin); - // Retrieves relative file path to the resources directory. + // Retrieves relative file path to the resource directory. // @param path writable memory to store the path // @param path_size number of available bytes in path // Returns the number of bytes in the path, or -1 on error diff --git a/include/clap/ext/draft/surround.h b/include/clap/ext/draft/surround.h index a96a6659..0f612653 100644 --- a/include/clap/ext/draft/surround.h +++ b/include/clap/ext/draft/surround.h @@ -24,7 +24,7 @@ // 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/2"; +static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND[] = "clap.surround.draft/3"; static CLAP_CONSTEXPR const char CLAP_PORT_SURROUND[] = "surround"; @@ -54,14 +54,13 @@ enum { }; typedef struct clap_plugin_surround { - // Stores into the channel_map array, the surround identifer of each channels. + // Stores into the channel_map array, the surround identifier of each channel. // Returns the number of elements stored in channel_map. // // 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] uint32_t(CLAP_ABI *get_channel_map)(const clap_plugin_t *plugin, - clap_id config_id, bool is_input, uint32_t port_index, uint8_t *channel_map, @@ -77,13 +76,6 @@ typedef struct clap_host_surround { // The channel map can only change when the plugin is de-activated. // [main-thread] void(CLAP_ABI *changed)(const clap_host_t *host); - - // Ask the host what is the prefered/project surround channel map. - // [main-thread] - void(CLAP_ABI *get_preferred_channel_map)(const clap_host_t *host, - uint8_t *channel_map, - uint32_t channel_map_capacity, - uint32_t *channel_count); } clap_host_surround_t; #ifdef __cplusplus diff --git a/include/clap/ext/draft/track-info.h b/include/clap/ext/draft/track-info.h index 6de63d0c..4f4db86d 100644 --- a/include/clap/ext/draft/track-info.h +++ b/include/clap/ext/draft/track-info.h @@ -4,9 +4,9 @@ #include "../../color.h" #include "../../string-sizes.h" -// This extensions let the plugin query info about the track it's in. +// 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 configuartion regarding audio port type and channel count. +// 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"; @@ -38,7 +38,7 @@ typedef struct clap_track_info { // track color, available if flags contain CLAP_TRACK_INFO_HAS_TRACK_COLOR clap_color_t color; - // availabe if flags contain CLAP_TRACK_INFO_HAS_AUDIO_CHANNEL + // 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; diff --git a/include/clap/ext/draft/tuning.h b/include/clap/ext/draft/tuning.h index 251b3a3e..57d2d84b 100644 --- a/include/clap/ext/draft/tuning.h +++ b/include/clap/ext/draft/tuning.h @@ -39,9 +39,9 @@ typedef struct clap_host_tuning { // The plugin may query the tuning at a rate that makes sense for *low* frequency modulations. // // If the tuning_id is not found or equals to CLAP_INVALID_ID, - // then the function shall gracefuly return a sensible value. + // then the function shall gracefully return a sensible value. // - // sample_offset is the sample offset from the begining of the current process block. + // sample_offset is the sample offset from the beginning of the current process block. // // should_play(...) should be checked before calling this function. // diff --git a/include/clap/ext/gui.h b/include/clap/ext/gui.h index c1f635a3..893d620c 100644 --- a/include/clap/ext/gui.h +++ b/include/clap/ext/gui.h @@ -99,7 +99,7 @@ typedef struct clap_plugin_gui { 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 host has no obligation to honor the plugin preference, 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] @@ -113,10 +113,12 @@ typedef struct clap_plugin_gui { // can set its window to stays above the parent window, see set_transient(). // api may be null or blank for floating window. // - // If is_floating is false, then the plugin has to embbed its window into the parent window, see + // If is_floating is false, then the plugin has to embed its window into the parent window, see // set_parent(). // // After this call, the GUI may not be visible yet; don't forget to call show(). + // + // Returns true if the GUI is successfuly created. // [main-thread] bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating); @@ -130,6 +132,8 @@ typedef struct clap_plugin_gui { // If the plugin prefers to work out the scaling factor itself by querying the OS directly, // then ignore the call. // + // scale = 2 means 200% scaling. + // // Returns true if the scaling could be applied // Returns false if the call was ignored, or the scaling could not be applied. // [main-thread] @@ -137,6 +141,8 @@ typedef struct clap_plugin_gui { // Get the current size of the plugin UI. // clap_plugin_gui->create() must have been called prior to asking the size. + // + // Returns true if the plugin could get the size. // [main-thread] bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); @@ -154,31 +160,44 @@ typedef struct clap_plugin_gui { // This method does not change the size. // // Only for embedded windows. + // + // Returns true if the plugin could adjust the given size. // [main-thread] bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); // Sets the window size. Only for embedded windows. + // + // Returns true if the plugin could resize its window to the given size. // [main-thread] bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height); - // Embbeds the plugin window into the given window. + // Embeds the plugin window into the given window. + // + // Returns true on success. // [main-thread & !floating] 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. + // + // Returns true on success. // [main-thread & floating] 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(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title); // Show the window. + // + // Returns true on success. // [main-thread] 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. + // + // Returns true on success. // [main-thread] bool(CLAP_ABI *hide)(const clap_plugin_t *plugin); } clap_plugin_gui_t; diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h index 106b75aa..df60725a 100644 --- a/include/clap/ext/params.h +++ b/include/clap/ext/params.h @@ -21,7 +21,7 @@ /// /// When the plugin changes a parameter value, it must inform the host. /// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush(). -/// If the user is adjusting the value, don't forget to mark the begining and end +/// If the user is adjusting the value, don't forget to mark the beginning and end /// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END /// events. /// @@ -55,8 +55,9 @@ /// - the plugin is responsible for sending the parameter value to its audio processor /// - call clap_host_params->request_flush() or clap_host->request_process(). /// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(), -/// send an automation event and don't forget to set begin_adjust, -/// end_adjust and should_record flags +/// send an automation event and don't forget to wrap the parameter change(s) +/// with CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END to define the +/// beginning and end of the gesture. /// /// IV. Turning a knob via automation /// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush(). @@ -74,7 +75,7 @@ /// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL) /// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) /// -/// CLAP allows the plugin to change the parameter range, yet the plugin developper +/// CLAP allows the plugin to change the parameter range, yet the plugin developer /// should be aware that doing so isn't without risk, especially if you made the /// promise to never change the sound. If you want to be 100% certain that the /// sound will not change with all host, then simply never change the range. @@ -89,7 +90,7 @@ /// should be stored as plain value in the document. /// /// If the host goes with the first approach, there will still be situation where the -/// sound may innevitably change. For example, if the plugin increase the range, there +/// sound may inevitably change. For example, if the plugin increase the range, there /// is an automation playing at the max value and on top of that an LFO is applied. /// See the following curve: /// . @@ -97,15 +98,29 @@ /// ..... . . /// before: . . and after: . . /// +/// Persisting parameter values: +/// +/// Plugins are responsible for persisting their parameter's values between +/// sessions by implementing the state extension. Otherwise parameter value will +/// not be recalled when reloading a project. Hosts should _not_ try to save and +/// restore parameter values for plugins that don't implement the state +/// extension. +/// /// Advice for the host: +/// /// - store plain values in the document (automation) /// - store modulation amount in plain value delta, not in percentage /// - when you apply a CC mapping, remember the min/max plain values so you can adjust +/// - do not implement a parameter saving fall back for plugins that don't +/// implement the state extension /// /// Advice for the plugin: +/// /// - think carefully about your parameter range when designing your DSP /// - avoid shrinking parameter ranges, they are very likely to change the sound /// - consider changing the parameter range as a tradeoff: what you improve vs what you break +/// - make sure to implement saving and loading the parameter values using the +/// state extension /// - if you plan to use adapters for other plugin formats, then you need to pay extra /// attention to the adapter requirements @@ -120,7 +135,7 @@ enum { // if so the double value is converted to integer using a cast (equivalent to trunc). CLAP_PARAM_IS_STEPPED = 1 << 0, - // Useful for for periodic parameters like a phase + // Useful for periodic parameters like a phase CLAP_PARAM_IS_PERIODIC = 1 << 1, // The parameter should not be shown to the user, because it is currently not used. @@ -191,7 +206,7 @@ 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 object by caching its pointer. + // Its purpose is to provide fast access to the plugin parameter object by caching its pointer. // For instance: // // in clap_plugin_params.get_info(): diff --git a/include/clap/ext/posix-fd-support.h b/include/clap/ext/posix-fd-support.h index c0147ce6..5bfd7bf9 100644 --- a/include/clap/ext/posix-fd-support.h +++ b/include/clap/ext/posix-fd-support.h @@ -24,7 +24,7 @@ typedef struct clap_plugin_posix_fd_support { // This callback is "level-triggered". // It means that a writable fd will continuously produce "on_fd()" events; // don't forget using modify_fd() to remove the write notification once you're - // done writting. + // done writing. // // [main-thread] void(CLAP_ABI *on_fd)(const clap_plugin_t *plugin, int fd, clap_posix_fd_flags_t flags); diff --git a/include/clap/ext/render.h b/include/clap/ext/render.h index 2a5e6135..0e1c1cde 100644 --- a/include/clap/ext/render.h +++ b/include/clap/ext/render.h @@ -24,7 +24,7 @@ typedef int32_t clap_plugin_render_mode; // If this information does not influence your rendering code, then don't // implement this extension. typedef struct clap_plugin_render { - // Returns true if the plugin has an hard requirement to process in real-time. + // Returns true if the plugin has a hard requirement to process in real-time. // This is especially useful for plugin acting as a proxy to an hardware device. // [main-thread] bool(CLAP_ABI *has_hard_realtime_requirement)(const clap_plugin_t *plugin); diff --git a/include/clap/ext/state.h b/include/clap/ext/state.h index c1c2cdca..8d028e1b 100644 --- a/include/clap/ext/state.h +++ b/include/clap/ext/state.h @@ -3,6 +3,14 @@ #include "../plugin.h" #include "../stream.h" +/// @page State +/// @brief state management +/// +/// Plugins can implement this extension to save and restore both parameter +/// 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. + static CLAP_CONSTEXPR const char CLAP_EXT_STATE[] = "clap.state"; #ifdef __cplusplus diff --git a/include/clap/ext/thread-check.h b/include/clap/ext/thread-check.h index 359ac887..7b68e1b0 100644 --- a/include/clap/ext/thread-check.h +++ b/include/clap/ext/thread-check.h @@ -14,7 +14,9 @@ extern "C" { /// /// 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. +/// This will be the same OS thread throughout the lifetime of the plug-in. +/// On macOS and Windows, this must be the thread on which gui and timer events are received +/// (i.e., the main thread of the program). /// 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. @@ -29,7 +31,7 @@ extern "C" { /// 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 +/// including the main-thread as the audio-thread, as long as it can guarantee 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]. diff --git a/include/clap/factory/draft/preset-discovery.h b/include/clap/factory/draft/preset-discovery.h index 6224a771..76a2e6ac 100644 --- a/include/clap/factory/draft/preset-discovery.h +++ b/include/clap/factory/draft/preset-discovery.h @@ -48,12 +48,24 @@ // 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-1"; + "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 itsel 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, @@ -62,7 +74,7 @@ enum clap_preset_discovery_flags { 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 additionnal features which the user + // 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, @@ -111,8 +123,8 @@ typedef struct clap_preset_discovery_metadata_receiver { // 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 must be null. + // 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 @@ -176,7 +188,7 @@ typedef struct clap_preset_discovery_metadata_receiver { typedef struct clap_preset_discovery_filetype { const char *name; - const char *description; + const char *description; // optional // `.' isn't included in the string. // If empty or NULL then every file should be matched. @@ -187,26 +199,23 @@ typedef struct clap_preset_discovery_filetype { 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 - // URI: - // - file:/// for pointing to a file or directory; directories are scanned recursively - // eg: file:///home/abique/.u-he/Diva/Presets/Diva (on Linux) - // eg: file:///C:/Users/abique/Documents/u-he/Diva.data/Presets/ (on Windows) - // - // - plugin:// for presets which are bundled within the plugin DSO. - // In that case, the uri must be exactly `plugin://` and nothing more. - const char *uri; + // 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 { - uint64_t flags; // see enum clap_preset_discovery_flags + 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; // reasonably short description of the sound pack - const char *homepage_url; // url to the pack's homepage - const char *vendor; // sound pack's vendor - const char *image_uri; // may be an image on disk or from an http server + 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; @@ -215,7 +224,7 @@ 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; // eg: u-he + const char *vendor; // optional, eg: u-he } clap_preset_discovery_provider_descriptor_t; // This interface isn't thread-safe. @@ -234,7 +243,8 @@ typedef struct clap_preset_discovery_provider { // reads metadata from the given file and passes them to the metadata receiver bool(CLAP_ABI *get_metadata)(const struct clap_preset_discovery_provider *provider, - const char *uri, + uint32_t location_kind, + const char *location, const clap_preset_discovery_metadata_receiver_t *metadata_receiver); // Query an extension. @@ -249,9 +259,9 @@ typedef struct clap_preset_discovery_provider { typedef struct clap_preset_discovery_indexer { clap_version_t clap_version; // initialized to CLAP_VERSION const char *name; // eg: "Bitwig Studio" - const char *vendor; // eg: "Bitwig GmbH" - const char *url; // eg: "https://bitwig.com" - const char *version; // eg: "4.3", see plugin.h for advice on how to format the version + 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 @@ -282,7 +292,7 @@ typedef struct clap_preset_discovery_indexer { } clap_preset_discovery_indexer_t; // Every methods in this factory must be thread-safe. -// It is encourraged to perform preset indexing in background threads, maybe even in background +// 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 diff --git a/include/clap/plugin-features.h b/include/clap/plugin-features.h index 7cccb022..e5dc18c5 100644 --- a/include/clap/plugin-features.h +++ b/include/clap/plugin-features.h @@ -6,7 +6,7 @@ // For practical reasons we'll avoid spaces and use `-` instead to facilitate // scripts that generate the feature array. // -// Non-standard features should be formated as follow: "$namespace:$feature" +// Non-standard features should be formatted as follow: "$namespace:$feature" ///////////////////// // Plugin category // @@ -48,6 +48,8 @@ #define CLAP_PLUGIN_FEATURE_DISTORTION "distortion" #define CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER "transient-shaper" #define CLAP_PLUGIN_FEATURE_COMPRESSOR "compressor" +#define CLAP_PLUGIN_FEATURE_EXPANDER "expander" +#define CLAP_PLUGIN_FEATURE_GATE "gate" #define CLAP_PLUGIN_FEATURE_LIMITER "limiter" #define CLAP_PLUGIN_FEATURE_FLANGER "flanger" diff --git a/include/clap/plugin.h b/include/clap/plugin.h index 7eead322..e366e051 100644 --- a/include/clap/plugin.h +++ b/include/clap/plugin.h @@ -77,7 +77,7 @@ typedef struct clap_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. + // envelopes, lfo, ...) and kills all voices. // - The parameter's value remain unchanged. // - clap_process.steady_time may jump backward. // diff --git a/include/clap/process.h b/include/clap/process.h index 746cb1f8..c9dbf923 100644 --- a/include/clap/process.h +++ b/include/clap/process.h @@ -53,11 +53,11 @@ typedef struct clap_process { uint32_t audio_inputs_count; uint32_t audio_outputs_count; - // Input and output events. - // - // Events must be sorted by time. // The input event list can't be modified. + // Input read-only event list. The host will deliver these sorted in sample order. const clap_input_events_t *in_events; + + // Output event list. The plugin must insert events in sample sorted order when inserting events const clap_output_events_t *out_events; } clap_process_t; diff --git a/include/clap/stream.h b/include/clap/stream.h index 3e8d9a91..b9b0b6cf 100644 --- a/include/clap/stream.h +++ b/include/clap/stream.h @@ -3,6 +3,18 @@ #include "private/std.h" #include "private/macros.h" +/// @page Streams +/// +/// ## Notes on using streams +/// +/// When working with `clap_istream` and `clap_ostream` objects to load and save +/// state, it is important to keep in mind that the host may limit the number of +/// bytes that can be read or written at a time. The return values for the +/// stream read and write functions indicate how many bytes were actually read +/// or written. You need to use a loop to ensure that you read or write the +/// entirety of your state. Don't forget to also consider the negative return +/// values for the end of file and IO error codes. + #ifdef __cplusplus extern "C" { #endif diff --git a/include/clap/version.h b/include/clap/version.h index 68139526..ff45ddf5 100644 --- a/include/clap/version.h +++ b/include/clap/version.h @@ -10,7 +10,7 @@ extern "C" { typedef struct clap_version { // This is the major ABI and API design // Version 0.X.Y correspond to the development stage, API and ABI are not stable - // Version 1.X.Y correspont to the release stage, API and ABI are stable + // Version 1.X.Y correspond to the release stage, API and ABI are stable uint32_t major; uint32_t minor; uint32_t revision; @@ -22,7 +22,7 @@ typedef struct clap_version { #define CLAP_VERSION_MAJOR 1 #define CLAP_VERSION_MINOR 1 -#define CLAP_VERSION_REVISION 7 +#define CLAP_VERSION_REVISION 8 #define CLAP_VERSION_INIT \ { (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION }