{"id":13730577,"url":"https://github.com/free-audio/clap-juce-extensions","last_synced_at":"2025-05-08T03:30:56.438Z","repository":{"id":37026614,"uuid":"440544917","full_name":"free-audio/clap-juce-extensions","owner":"free-audio","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-17T13:31:55.000Z","size":248,"stargazers_count":138,"open_issues_count":7,"forks_count":19,"subscribers_count":11,"default_branch":"main","last_synced_at":"2024-08-04T02:09:53.154Z","etag":null,"topics":["clap","juce"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/free-audio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-21T14:29:03.000Z","updated_at":"2024-07-24T20:06:06.000Z","dependencies_parsed_at":"2023-02-18T19:46:00.415Z","dependency_job_id":"97f4878e-8ce9-43c4-96f9-222e654a98ab","html_url":"https://github.com/free-audio/clap-juce-extensions","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/free-audio%2Fclap-juce-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/free-audio%2Fclap-juce-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/free-audio%2Fclap-juce-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/free-audio%2Fclap-juce-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/free-audio","download_url":"https://codeload.github.com/free-audio/clap-juce-extensions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224695569,"owners_count":17354431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clap","juce"],"created_at":"2024-08-03T02:01:16.775Z","updated_at":"2025-05-08T03:30:56.428Z","avatar_url":"https://github.com/free-audio.png","language":"C++","funding_links":[],"categories":["Integrations"],"sub_categories":[],"readme":"# JUCE6, 7 and 8 Unofficial CLAP Plugin Support\n\nThis is a set of code which, combined with a JUCE 6 or JUCE 7 plugin project, allows you to build a CLAP plugin. It\nis licensed under the MIT license, and can be used for both open and closed source projects.\n\nWe are labeling it 'unofficial' for four reasons\n\n1. It is not supported by the JUCE team,\n2. There are some JUCE features which we have not translated to CLAP yet,\n3. It presents a set of completely optional extensions which break JUCE abstractions to allow extended CLAP feature\n   support and\n4. It does not support JUCE-based CLAP hosting\n\nDespite those caveats, the basic use of this library has allowed a wide variety\nof synths and effects to generate a CLAP from their JUCE program, including Surge, B-Step,\nMonique, several ChowDSP plugins, Dexed and more.\n\nBy far the best solution for CLAP in JUCE would be full native support by the JUCE team. Until such a time as that\nhappens (and it may never happen), this code may help you if you have a JUCE plugin and want to generate a CLAP. We are\nhappy to merge changes and answer questions as you try to use it. Please feel free to raise github issues in this repo.\n\nThis version is based off of CLAP 1.0 and generates plugins which work in BWS 4.3beta5 and later, as well as\nother CLAP 1.0 DAWs such as MultitrackStudio.\n\n## Basics: Using these extensions to build a CLAP\n\n### CMake\n\nGiven a starting point of a JUCE plugin using CMake which can build a VST3, AU, Standalone and so forth with\n`juce_plugin`, building a CLAP is a simple exercise of checking out this CLAP extension code\nsomewhere in your dev environment, setting a few CMake variables, and adding a couple of lines to your CMake file.\n\nThe instructions are as follows:\n\n1. Add `https://github.com/free-audio/clap-juce-extensions.git` as a submodule of your project, or otherwise make the\n   source available to your cmake (CPM, side by side check out in CI, etc...). For example:\n\n```git\ngit submodule add -b main https://github.com/free-audio/clap-juce-extensions.git libs/clap-juce-extensions\ngit submodule update --init --recursive # important, this will grab clap and clap-helpers\n```\n   \n2. Load the `clap-juce-extension` in your CMake after you have loaded JUCE. For instance, you could do\n\n```cmake\nadd_subdirectory(libs/JUCE) # this is however you load juce\nadd_subdirectory(libs/clap-juce-extensions EXCLUDE_FROM_ALL) \n```\n\n3. Create your JUCE plugin as normal with flags and formats using the `juce_plugin` CMake function\n4. After your `juce_plugin` code, add the following lines (or similar)\n   to your CMake (a list of pre-defined CLAP\n   features can be found [here](https://github.com/free-audio/clap/blob/main/include/clap/plugin-features.h)):\n\n```cmake\n    clap_juce_extensions_plugin(TARGET my-target\n        CLAP_ID \"com.my-cool-plugs.my-target\"\n        CLAP_FEATURES instrument \"virtual analog\" gritty basses leads pads)\n```\n\n5. Reload your CMake file and you will have a new target `my-target_CLAP` which will build a CLAP and leave\n   it side-by-side with your AU, Standalone, VST3, and so forth. Load that CLAP into a DAW and give it a whirl!\n\n### Projucer\n\nGiven a starting point of a JUCE plugin using the Projucer, it is possible to build a CLAP plugin by adding\na small CMake configuration alongside the Projucer build setup. Note that for MacOS and Linux, it is expected\nthat the \"xmllint\" tool is available in the system path.\n\n1. Build your Projucer-based plugin.\n2. Create `CMakeLists.txt` file in the same directory as your `.jucer` file. Here's an example CMakeLists.txt:\n\n```cmake\ncmake_minimum_required(VERSION 3.15)\n\n# Make sure to set the same C++ version as you have set in the Projucer\nset(CMAKE_CXX_STANDARD 17)\n\n# Make sure to set the same MacOS deployment target as you have set in the Projucer\nset(CMAKE_OSX_DEPLOYMENT_TARGET \"10.12\" CACHE STRING \"Minimum OS X deployment target\")\n\n# If you want to build a universal binary on Mac by default, you may want to include this line\n# set(CMAKE_OSX_ARCHITECTURES \"arm64;x86_64\")\n\n# If the Projucer is using \"static runtime\" for Visual Studio:\n# set(CMAKE_MSVC_RUNTIME_LIBRARY \"MultiThreaded$\u003c$\u003cCONFIG:Debug\u003e:Debug\u003e\" CACHE STRING \"Runtime\")\n# set(CMAKE_MSVC_RUNTIME_LIBRARY \"MultiThreaded$\u003c$\u003cCONFIG:Release\u003e:Release\u003e\" CACHE STRING \"Runtime\")\n\n# If running into issues when Xcode tries to codesign the CLAP plugin, you may want to add these lines:\n# set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED \"NO\")\n# set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED \"NO\")\n\nproject(MyPlugin VERSION 1.0.0)\n\nset(PATH_TO_JUCE path/to/JUCE)\nset(PATH_TO_CLAP_EXTENSIONS path/to/clap-juce-extensions)\n\n# define the exporter types used in your Projucer configuration\nif (APPLE)\n    set(JUCER_GENERATOR \"Xcode\")\nelseif (WIN32)\n    set(JUCER_GENERATOR \"VisualStudio2019\")\nelse () # Linux\n    set(JUCER_GENERATOR \"LinuxMakefile\")\nendif ()\n\ninclude(${PATH_TO_CLAP_EXTENSIONS}/cmake/JucerClap.cmake)\ncreate_jucer_clap_target(\n        TARGET MyPlugin # \"Binary Name\" in the Projucer\n        PLUGIN_NAME \"My Plugin\"\n        BINARY_NAME \"MyPlugin\" # Name of the resulting plugin binary\n        MANUFACTURER_NAME \"My Company\"\n        MANUFACTURER_CODE Manu\n        PLUGIN_CODE Plg1\n        VERSION_STRING \"1.0.0\"\n        CLAP_ID \"org.mycompany.myplugin\"\n        CLAP_FEATURES instrument synthesizer\n        CLAP_MANUAL_URL \"https://www.mycompany.com\"\n        CLAP_SUPPORT_URL \"https://www.mycompany.com\"\n        EDITOR_NEEDS_KEYBOARD_FOCUS FALSE\n)\n```\n\n3. Build the CLAP plugin using CMake. This step can be done manually,\n   as part of an automated build script, or potentially even as a\n   post-build step triggered from the Projucer:\n\n```bash\ncmake -Bbuild-clap -G\u003cgenerator\u003e -DCMAKE_BUILD_TYPE=\u003cDebug|Release\u003e\ncmake --build build-clap --config \u003cDebug|Release\u003e\n```\n\nThe resulting builds will be located in `build-clap/MyPlugin_artefacts`.\n\nIf you would like to use the [CLAP extensions API](#the-extensions-api), the necessary source\nfiles must be added to the plugin's Projucer configuration.\n\n### Arguments to CLAP CMake functions\n\nIn addition to `CLAP_ID` and `CLAP_FEATURES` described above the following arguments\nare available\n\n* `CLAP_MANUAL_URL` and `CLAP_SUPPORT_URL` generate the urls in your description\n* `CLAP_MISBHEAVIOUR_HANDLER_LEVEL` can be set to `Terminate` or `Ignore` (default\n  is `Ignore`) to choose your behaviour for a misbehaving host.\n* `CLAP_CHECKING_LEVEL` can be set to `None`, `Minimal`, or `Maximal` (default is\n  `Minimal`) to choose the level of sanity checks enabled for the plugin.\n* `CLAP_PROCESS_EVENTS_RESOLUTION_SAMPLES` can be set to any integer value to choose the\n  resolution (in samples) used by the wrapper for doing sample-accurate event processing.\n  Setting the value to `0` (the default value) will turn off sample-accurate event processing.\n* `CLAP_ALWAYS_SPLIT_BLOCK` can be set to `1` (on), or `0` (off, default), to tell the\n  wrapper to _always_ attempt to split incoming audio buffers into chunks of size\n  `CLAP_PROCESS_EVENTS_RESOLUTION_SAMPLES`, regardless of any input events being\n  sent from the host. Note that if the block size provided by the host is not an\n  even multiple of `CLAP_PROCESS_EVENTS_RESOLUTION_SAMPLES`, the plugin may be\n  required to process a chunk smaller than the chosen resolution.\n* `CLAP_USE_JUCE_PARAMETER_RANGES` can be set to `ALL`, `DISCRETE` or `OFF` (default) to\n  tell the wrapper to use JUCE's parameter ranges for all parameters, discrete parameters only,\n  or no parameters. When not using JUCE's parameter ranges, the plugin will communicate with\n  the host using 0-1 parameter ranges for the given parameter,\n\n## Risks of using this library\n\nUsing this library is, of course, not without risks. There could easily be bugs we haven't found and there are\nAPIs we don't cover. We are happy to discuss, investigate, and work to fix any of those.\n\nThe biggest risk, though, involves JUCE team providing official support in a way which is fundamentally incompatible\nwith these wrappers. As of this writing, the JUCE team has not committed to supporting CLAP in JUCE 7 or any future\nversion, although they are aware of the project. But if the JUCE team did provide official future support, it is not\nclear that your CLAP plugin which resulted from their official support would work in the same way as the plugin\ngenerated by this library would.\n\nThere are a couple of mitigants to that risk.\n\nMost importantly, in the three critical places a DAW interacts with a plugin - CLAP ID, parameter IDs, and state\nstreaming -\nwe have endeavoured to write in as JUCE-natural a way as possible.\n\n1. The CLAP ID is just a CMake parameter, as we expect it would be in an official build.\n2. The parameter IDs we use uses the [internal JUCE hashing mechanism to generate\n   our `uint32_t`](https://github.com/free-audio/clap-juce-extensions/blob/85bc0d56dc784a5f1271602db46f0748954b180e/src/wrapper/clap-juce-wrapper.cpp#L198)\n   just like\n   the [current VST3 wrapper does](https://github.com/juce-framework/JUCE/blob/2f980209cc4091a4490bb1bafc5d530f16834e58/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp#L585).\n3. Our stream implementation\n   transparently [calls `AudioProcessor::setStateInformation` and `AudioProcessor::getStateInformation`](https://github.com/free-audio/clap-juce-extensions/blob/85bc0d56dc784a5f1271602db46f0748954b180e/src/wrapper/clap-juce-wrapper.cpp#L930)\n   with no intervening\n   modification of the stream.\n\nWhile there is no guarantee that an official JUCE implementation, if it were to exist, would make these choices,\nit seems quite natural that it would, and in that case, your plugin would continue to work.\n\nIf, however, you use the extensions detailed below - which allows features outside of JUCE like note expressions,\nsample accurate automation, and polyphonic and non-destructive modulation - there is very little assurance we can\ngive you that an official JUCE implementation, if it were to exist, would work with your code without modification,\nor even that it would support those features at all. That would leave such a synth (of which Surge is the primary\nexample today) relying on these wrappers still.\n\n## Major Missing API points\n\n1. We have not tested any JUCE version earlier than 6.0.7, and plugins which use deprecated APIs may not work\n2. The [`AudioProcessor::WrapperType`](https://docs.juce.com/master/classAudioProcessor.html#a2e1b21b8831ac529965abffc96223dcf)\n   API doesn't support CLAP. All CLAP plugins will define a `wrapperType` of `wrapperType_Undefined`. We do provide\n   a workaround for using our extensions mechanism, below.\n3. Several parameter features - including discrete (stepped) parameters - don't translate from JUCE to CLAP\n   in our adapter (although they are supported in the CLAP API of course). We would love a test plugin to help us\n   resolve this.\n\n## The `clap_juce_extensions` API for extended CLAP capabilities in JUCE\n\nThere are a set of things which JUCE doesn't support which CLAP does. Rather than not support them in our\nplugins, we've decided to create an specific extensions API which allow you to decorate JUCE\nclasses with extended capabilities. These are a set of classes which your AudioProcessor can\nimplement and, if it does, then the CLAP JUCE wrapper will call the associated functions.\n\nThe extension are in \"include/clap-juce-extensions.h\" and are documented there, but currently have\nthree classes\n\n- `clap_juce_extensions::clap_properties`\n    - if you subclass this your AudioProcessor will have a collection of members which give you extra CLAP info\n    - Most usefully, you get an `is_clap` member which is false if not a CLAP and true if it is, which works around\n      the fact that our 'forkless' approach doesn't let us add a `AudioProcessor::WrapperType` to the JUCE API\n- `clap_juce_extensions::clap_juce_audio_processor_capabilities`\n    - these are a set of advanced extensions which let you optionally interact more directly with the CLAP API\n      and are mostly useful for advanced features like non-destructive modulation and note expression support\n- `clap_juce_extensions::clap_juce_parameter_capabilities`\n    - If your AudioProcessorParameter subclass implements this API, you can share extended CLAP information on\n      a parameter by parameter basis\n\nAs an example, here's how to use `clap_properties` to work around `AudioProcessor::WrapperType` being `Undefined` in the\nforkless\nCLAP approach\n\n- `#include \"clap-juce-extensions/clap-juce-extensions.h\"`\n- Make your main plugin `juce::AudioProcessor` derive from `clap_juce_extensions::clap_properties`\n- Use the `is_clap` member variable to figure out the correct wrapper type.\n\nHere's a minimal example:\n\n```cpp\n#include \u003cJuceHeader.h\u003e\n#include \"clap-juce-extensions/clap-juce-extensions.h\"\n\nclass MyCoolPlugin : public juce::AudioProcessor,\n                     public clap_juce_extensions::clap_properties\n{\n    String getWrapperTypeString()\n    {\n        if (wrapperType == wrapperType_Undefined \u0026\u0026 is_clap)\n            return \"CLAP\";\n    \n        return juce::AudioProcessor::getWrapperTypeDescription (wrapperType);\n    }\n    \n    ...\n};\n```\n\nIf you are interested in using these extensions, please consult the documentation in the\n[clap-juce-extensions header.](https://github.com/free-audio/clap-juce-extensions/blob/main/include/clap-juce-extensions/clap-juce-extensions.h)\nThe [Surge XT Synthesizer](https://github.com/surge-synthesizer/surge) is a worked example of using many of these.\nWe are also happy to discuss them - reach out in the issues here or in a shared discord server.\n\n## Technical Detail: The \"Forkless\" approach\n\nThere's a couple of ways we could have gone adding experimental JUCE support. The way the LV2 extensions to JUCE work\nrequires a forked JUCE which places LV2 support fully inside the JUCE ecosystem at the cost of maintaining a fork (and\nnot allowing folks with their own forks to easily use LV2). We instead chose an 'out-of-JUCE' approach which has the\nfollowing pros and cons\n\nPros:\n\n* You can use any JUCE 6 or 7 / CMake method you want and don't need to use our branch.\n* We don't have to update our fork to pull latest JUCE features; you don't have to use our fork and choices to build\n  your plugin.\n\nCons:\n\n* The CMake API is not consistent. Rather than add \"CLAP\" as a plugin type, you need a couple of extra lines of CMake to\n  activate your CLAP.\n* We cannot support the `AudioProcessor::WrapperType` API, as discussed above.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffree-audio%2Fclap-juce-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffree-audio%2Fclap-juce-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffree-audio%2Fclap-juce-extensions/lists"}