diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 88040a96..7b9ccd9a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -39,8 +39,17 @@ jobs: - name: Run CMake+Ninja+CTest to generate/build/test. uses: lukka/run-cmake@v10 - id: runcmake + id: runcmake-ninja with: configurePreset: 'ninja' buildPreset: 'ninja-release' testPreset: 'ninja-release' + + - name: Run CMake+MSVC+CTest to generate/build/test. + uses: lukka/run-cmake@v10 + if: startsWith(matrix.os, 'win') + id: runcmake-msvc + with: + configurePreset: 'msvc' + buildPreset: 'msvc-release' + testPreset: 'msvc-release' diff --git a/CMakeLists.txt b/CMakeLists.txt index c386acf0..8773c35f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,10 @@ if (${CLAP_BUILD_TESTS}) add_test(NAME test-clap-compile-${SUFFIX} COMMAND clap-compile-${SUFFIX}) add_dependencies(clap-tests clap-compile-${SUFFIX}) + if (${EXT} STREQUAL "cc") + target_compile_definitions(clap-compile-${SUFFIX} PRIVATE CLAP_COMPILE_TEST_CXX_VERSION=${STDCPP}) + endif() + if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang") target_compile_options(clap-compile-${SUFFIX} PRIVATE -Wall -Wextra -pedantic) endif() diff --git a/CMakePresets.json b/CMakePresets.json index d707bfb9..bd0b1c51 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -22,6 +22,23 @@ "value": true } } + }, + { + "name": "msvc", + "displayName": "MSVC", + "description": "Configure and generate MSVC project files for all configurations", + "binaryDir": "${sourceDir}/builds/${presetName}", + "generator": "Visual Studio 17 2022", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "boolean", + "value": true + }, + "CLAP_BUILD_TESTS": { + "type": "boolean", + "value": true + } + } } ], "buildPresets": [ @@ -32,6 +49,14 @@ "description": "Build ninja Release configuration", "configuration": "RelWithDebInfo", "targets": ["clap-tests"] + }, + { + "name": "msvc-release", + "configurePreset": "msvc", + "displayName": "Build msvc-release", + "description": "Build msvc Release configuration", + "configuration": "RelWithDebInfo", + "targets": ["clap-tests"] } ], "testPresets": [ @@ -39,6 +64,11 @@ "name": "ninja-release", "configurePreset": "ninja", "configuration": "RelWithDebInfo" + }, + { + "name": "msvc-release", + "configurePreset": "msvc", + "configuration": "RelWithDebInfo" } ] } \ No newline at end of file diff --git a/ChangeLog.md b/ChangeLog.md index cfd44bcd..cce7a328 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,13 @@ +# Changes in 1.1.9 + +* [entry.h](include/clap/entry.h): clarify what the `plugin_path` is on macOS +* [surround.h](include/clap/ext/draft/surround.h): simplify the design +* [ambisonic.h](include/clap/ext/draft/ambisonic.h): simplify the design +* [configurable-audio-ports.h](include/clap/ext/draft/configurable-audio-ports.h): simplify the design +* [gui.h](include/clap/ext/gui.h): documentation clarifications +* [entry.h](include/clap/entry.h): documentation clarifications +* [audio-ports-activation.h](include/clap/ext/draft/audio-ports-activation.h): specify the sample size to be used when activating the audio port. + # Changes in 1.1.8 * [params.h](include/clap/ext/params.h): document how persisting parameter values between sessions should be implemented @@ -126,7 +136,7 @@ it is now **required** to deactivate the plugin before destroying it. * [params.h](include/clap/ext/params.h): improve documentation for `clap_host_params->request_flush()`. * [entry.h](include/clap/entry.h): improve documentation regarding `init()`, `deinit()` and CLAP search path. -* [gui.h](inclued/clap/gui.h): fix typo `clap_gui_resize_hints.preserve_aspect_ratio` +* [gui.h](include/clap/gui.h): fix typo `clap_gui_resize_hints.preserve_aspect_ratio` * [plugin-template](src/plugin-template.c): missing impl of plugin destroy. * various documentation improvements diff --git a/README.md b/README.md index ddf6369a..52dc263c 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,14 @@ # Learn about CLAP -CLAP stands for **CL**ever **A**udio **P**lugin. -It is an audio plugin ABI which defines a standard for *Digital Audio Workstations* and audio plugins (synthesizers, audio effects, ...) to work together. +CLAP stands for **CL**ever **A**udio **P**lugin. It is an interface that +provides a stable ABI to define a standard for *Digital Audio Workstations* and +audio plugins (synthesizers, audio effects, ...) to work together. + +The ABI, or **A**pplication **B**inary **I**nterface, serves as a means of +communication between a host and a plugin. It provides backwards compatibility, +that is, a plugin binary compiled with CLAP 1.x can be loaded by any other +CLAP 1.y. To work with CLAP, include [clap/clap.h](include/clap/clap.h). diff --git a/include/clap/entry.h b/include/clap/entry.h index 33f07948..c1f9d9c3 100644 --- a/include/clap/entry.h +++ b/include/clap/entry.h @@ -48,6 +48,8 @@ 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. + // + // plugin_path is the path to the DSO (Linux, Windows), or the bundle (macOS). bool(CLAP_ABI *init)(const char *plugin_path); // No more calls into the DSO must be made after calling deinit(). diff --git a/include/clap/ext/audio-ports.h b/include/clap/ext/audio-ports.h index d5b4a040..46186e76 100644 --- a/include/clap/ext/audio-ports.h +++ b/include/clap/ext/audio-ports.h @@ -49,7 +49,7 @@ typedef struct clap_audio_port_info { uint32_t channel_count; // If null or empty then it is unspecified (arbitrary audio). - // This filed can be compared against: + // This field can be compared against: // - CLAP_PORT_MONO // - CLAP_PORT_STEREO // - CLAP_PORT_SURROUND (defined in the surround extension) diff --git a/include/clap/ext/draft/ambisonic.h b/include/clap/ext/draft/ambisonic.h index 285a2979..556af9a6 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/2"; +static CLAP_CONSTEXPR const char CLAP_EXT_AMBISONIC[] = "clap.ambisonic.draft/3"; static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic"; @@ -12,15 +12,15 @@ static CLAP_CONSTEXPR const char CLAP_PORT_AMBISONIC[] = "ambisonic"; extern "C" { #endif -enum { +enum clap_ambisonic_ordering { // FuMa channel ordering - CLAP_AMBISONIC_FUMA = 0, + CLAP_AMBISONIC_ORDERING_FUMA = 0, // ACN channel ordering - CLAP_AMBISONIC_ACN = 1, + CLAP_AMBISONIC_ORDERING_ACN = 1, }; -enum { +enum clap_ambisonic_normalization { CLAP_AMBISONIC_NORMALIZATION_MAXN = 0, CLAP_AMBISONIC_NORMALIZATION_SN3D = 1, CLAP_AMBISONIC_NORMALIZATION_N3D = 2, @@ -28,21 +28,26 @@ enum { CLAP_AMBISONIC_NORMALIZATION_N2D = 4, }; -typedef struct clap_ambisonic_info { - uint32_t ordering; - uint32_t normalization; -} clap_ambisonic_info_t; +typedef struct clap_ambisonic_config { + uint32_t ordering; // see clap_ambisonic_ordering + uint32_t normalization; // see clap_ambisonic_normalization +} clap_ambisonic_config_t; typedef struct clap_plugin_ambisonic { + // Returns true if the given configuration is supported. + // [main-thread] + bool(CLAP_ABI *is_config_supported)(const clap_plugin_t *plugin, + const clap_ambisonic_config_t *config); + // Returns true on success // // config_id: the configuration id, see clap_plugin_audio_ports_config. // If config_id is CLAP_INVALID_ID, then this function queries the current port info. // [main-thread] - bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, - bool is_input, - uint32_t port_index, - clap_ambisonic_info_t *info); + bool(CLAP_ABI *get_config)(const clap_plugin_t *plugin, + bool is_input, + uint32_t port_index, + clap_ambisonic_config_t *config); } clap_plugin_ambisonic_t; diff --git a/include/clap/ext/draft/audio-ports-activation.h b/include/clap/ext/draft/audio-ports-activation.h index 63fb31e8..f451c005 100644 --- a/include/clap/ext/draft/audio-ports-activation.h +++ b/include/clap/ext/draft/audio-ports-activation.h @@ -26,7 +26,7 @@ /// clap_host_audio_ports.rescan(CLAP_AUDIO_PORTS_RESCAN_LIST). static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS_ACTIVATION[] = - "clap.audio-ports-activation/draft-1"; + "clap.audio-ports-activation/draft-2"; #ifdef __cplusplus extern "C" { @@ -42,12 +42,16 @@ typedef struct clap_plugin_audio_ports_activation { // It is only possible to activate and de-activate on the audio-thread if // can_activate_while_processing() returns true. // + // sample_size indicate if the host will provide 32 bit audio buffers or 64 bits one. + // Possible values are: 32, 64 or 0 if unspecified. + // // returns false if failed, or invalid parameters // [active ? audio-thread : main-thread] bool(CLAP_ABI *set_active)(const clap_plugin_t *plugin, bool is_input, uint32_t port_index, - bool is_active); + bool is_active, + uint32_t sample_size); } clap_plugin_audio_ports_activation_t; #ifdef __cplusplus diff --git a/include/clap/ext/draft/configurable-audio-ports.h b/include/clap/ext/draft/configurable-audio-ports.h index 57de8057..4fe60cd1 100644 --- a/include/clap/ext/draft/configurable-audio-ports.h +++ b/include/clap/ext/draft/configurable-audio-ports.h @@ -9,13 +9,9 @@ extern "C" { // 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"; + "clap.configurable-audio-ports.draft1"; 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; @@ -30,27 +26,30 @@ typedef struct clap_audio_port_configuration_request { // - 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 + // - CLAP_PORT_AMBISONIC: const clap_ambisonic_config_t *info const void *port_details; } clap_audio_port_configuration_request_t; typedef struct clap_plugin_configurable_audio_ports { - // 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. + // Returns true if the given configurations can be applied using apply_configuration(). // [main-thread && !active] - bool(CLAP_ABI *is_port_configurable)(const clap_plugin_t *plugin, - bool is_input, - uint32_t port_index); + bool(CLAP_ABI *can_apply_configuration)( + const clap_plugin_t *plugin, + const struct clap_audio_port_configuration_request *requests, + uint32_t request_count); // Submit a bunch of configuration requests which will atomically be applied together, // or discarded together. + // + // Once the configuration is successfully applied, it isn't necessary for the plugin to call + // clap_host_audio_ports->changed(); and it isn't necessary for the host to scan the + // audio ports. + // + // Returns true if applied. // [main-thread && !active] - bool(CLAP_ABI *request_configuration)( - const clap_plugin_t *plugin, - const struct clap_audio_port_configuration_request *requests, - uint32_t request_count); + bool(CLAP_ABI *apply_configuration)(const clap_plugin_t *plugin, + const struct clap_audio_port_configuration_request *requests, + uint32_t request_count); } clap_plugin_configurable_audio_ports_t; #ifdef __cplusplus diff --git a/include/clap/ext/draft/resource-directory.h b/include/clap/ext/draft/resource-directory.h index 1d96da5f..fc65eaa8 100644 --- a/include/clap/ext/draft/resource-directory.h +++ b/include/clap/ext/draft/resource-directory.h @@ -44,7 +44,7 @@ extern "C" { typedef struct clap_plugin_resource_directory { // Sets the directory in which the plugin can save its resources. - // The directory remains valid until it is overriden or the plugin is destroyed. + // The directory remains valid until it is overridden or the plugin is destroyed. // If path is null or blank, it clears the directory location. // path must be absolute. // [main-thread] diff --git a/include/clap/ext/draft/surround.h b/include/clap/ext/draft/surround.h index 0f612653..82f4e888 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/3"; +static CLAP_CONSTEXPR const char CLAP_EXT_SURROUND[] = "clap.surround.draft/4"; static CLAP_CONSTEXPR const char CLAP_PORT_SURROUND[] = "surround"; @@ -54,21 +54,21 @@ enum { }; typedef struct clap_plugin_surround { - // Stores into the channel_map array, the surround identifier of each channel. + // Checks if a given channel mask is supported. + // The channel mask is a bitmask, for example: + // (1 << CLAP_SURROUND_FL) | (1 << CLAP_SURROUND_FR) | ... + // [main-thread] + bool(CLAP_ABI *is_channel_mask_supported)(const clap_plugin_t *plugin, uint64_t channel_mask); + + // Stores the surround identifier of each channel into the channel_map array. // Returns the number of elements stored in channel_map. - // - // 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. + // channel_map_capacity must be greater or equal to the channel count of the given port. // [main-thread] uint32_t(CLAP_ABI *get_channel_map)(const clap_plugin_t *plugin, bool is_input, uint32_t port_index, uint8_t *channel_map, uint32_t channel_map_capacity); - - // Informs the plugin that the host preferred channel map has changed. - // [main-thread] - void(CLAP_ABI *changed)(const clap_plugin_t *plugin); } clap_plugin_surround_t; typedef struct clap_host_surround { diff --git a/include/clap/ext/gui.h b/include/clap/ext/gui.h index 893d620c..e6df6056 100644 --- a/include/clap/ext/gui.h +++ b/include/clap/ext/gui.h @@ -118,7 +118,7 @@ typedef struct clap_plugin_gui { // // After this call, the GUI may not be visible yet; don't forget to call show(). // - // Returns true if the GUI is successfuly created. + // Returns true if the GUI is successfully created. // [main-thread] bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating); @@ -147,28 +147,25 @@ typedef struct clap_plugin_gui { 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] + // [main-thread & !floating] 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] + // [main-thread & !floating] 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. // This method does not change the size. // - // Only for embedded windows. - // // Returns true if the plugin could adjust the given size. - // [main-thread] + // [main-thread & !floating] bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); - // Sets the window size. Only for embedded windows. + // Sets the window size. // // Returns true if the plugin could resize its window to the given size. - // [main-thread] + // [main-thread & !floating] bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height); // Embeds the plugin window into the given window. @@ -204,7 +201,7 @@ typedef struct clap_plugin_gui { typedef struct clap_host_gui { // The host should call get_resize_hints() again. - // [thread-safe] + // [thread-safe & !floating] void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host); /* Request the host to resize the client area to width, height. @@ -215,7 +212,7 @@ typedef struct clap_host_gui { * acknowledged the request and will process it asynchronously. If the request then can't be * satisfied then the host will call set_size() to revert the operation. * - * [thread-safe] */ + * [thread-safe & !floating] */ bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height); /* Request the host to show the plugin gui. diff --git a/include/clap/ext/latency.h b/include/clap/ext/latency.h index ca068cab..862b3341 100644 --- a/include/clap/ext/latency.h +++ b/include/clap/ext/latency.h @@ -10,7 +10,7 @@ extern "C" { // The audio ports scan has to be done while the plugin is deactivated. typedef struct clap_plugin_latency { - // Returns the plugin latency. + // Returns the plugin latency in samples. // [main-thread] uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin); } clap_plugin_latency_t; diff --git a/include/clap/factory/draft/preset-discovery.h b/include/clap/factory/draft/preset-discovery.h index 76a2e6ac..db26f1e9 100644 --- a/include/clap/factory/draft/preset-discovery.h +++ b/include/clap/factory/draft/preset-discovery.h @@ -61,7 +61,7 @@ enum clap_preset_discovery_location_kind { 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 + // The location must then be null, as the preset are within the plugin itself and then the plugin // will act as a preset container. CLAP_PRESET_DISCOVERY_LOCATION_PLUGIN = 1, }; diff --git a/include/clap/plugin.h b/include/clap/plugin.h index e366e051..2fd6530d 100644 --- a/include/clap/plugin.h +++ b/include/clap/plugin.h @@ -16,7 +16,7 @@ typedef struct clap_plugin_descriptor { // Otherwise the fields can be null or blank, though it is safer to make them blank. // // Some indications regarding id and version - // - id is an arbritrary string which should be unique to your plugin, + // - id is an arbitrary string which should be unique to your plugin, // we encourage you to use a reverse URI eg: "com.u-he.diva" // - version is an arbitrary string which describes a plugin, // it is useful for the host to understand and be able to compare two different diff --git a/include/clap/private/macros.h b/include/clap/private/macros.h index 15b6b1b3..ba1d6656 100644 --- a/include/clap/private/macros.h +++ b/include/clap/private/macros.h @@ -25,20 +25,26 @@ # endif #endif -#if defined(__cplusplus) && __cplusplus >= 201103L +#if defined(_MSVC_LANG) +# define CLAP_CPLUSPLUS _MSVC_LANG +#elif defined(__cplusplus) +# define CLAP_CPLUSPLUS __cplusplus +#endif + +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 201103L # define CLAP_HAS_CXX11 # define CLAP_CONSTEXPR constexpr #else # define CLAP_CONSTEXPR #endif -#if defined(__cplusplus) && __cplusplus >= 201703L +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 201703L # define CLAP_HAS_CXX17 # define CLAP_NODISCARD [[nodiscard]] #else # define CLAP_NODISCARD #endif -#if defined(__cplusplus) && __cplusplus >= 202002L +#if defined(CLAP_CPLUSPLUS) && CLAP_CPLUSPLUS >= 202002L # define CLAP_HAS_CXX20 #endif diff --git a/include/clap/version.h b/include/clap/version.h index ff45ddf5..1b9cc234 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 1 -#define CLAP_VERSION_REVISION 8 +#define CLAP_VERSION_REVISION 9 #define CLAP_VERSION_INIT \ { (uint32_t)CLAP_VERSION_MAJOR, (uint32_t)CLAP_VERSION_MINOR, (uint32_t)CLAP_VERSION_REVISION } diff --git a/src/main.cc b/src/main.cc index 949d0bb8..80febfba 100644 --- a/src/main.cc +++ b/src/main.cc @@ -48,6 +48,18 @@ #error CLAP_VERSION_LT is inconsistent (REVISION) #endif +#if (CLAP_COMPILE_TEST_CXX_VERSION >= 11) && ! defined(CLAP_HAS_CXX11) +#error CLAP_HAS_CXX11 is not defined correctly +#endif + +#if (CLAP_COMPILE_TEST_CXX_VERSION >= 17) && ! defined(CLAP_HAS_CXX17) +#error CLAP_HAS_CXX17 is not defined correctly +#endif + +#if (CLAP_COMPILE_TEST_CXX_VERSION >= 20) && ! defined(CLAP_HAS_CXX20) +#error CLAP_HAS_CXX20 is not defined correctly +#endif + static const CLAP_CONSTEXPR clap_version m = CLAP_VERSION; int main(int, char **) {