This repo serves as an example to demonstrate how to create a CLAP plugin.
The GUI is written with Dear ImGui, which is a submodule, and rendered in software into a pixel buffer. It doesn't need any library besides the system ones, nor any GPU context: each platform only has to show the pixels and to report the mouse events.
| Platform | Window API | Embedded | Floating |
|---|---|---|---|
| Linux | X11 | yes | yes |
| Linux | Wayland | experimental, through the host's compositor (1) | experimental (1) |
| Windows | Win32 | yes | yes |
| macOS | Cocoa | yes | yes |
(1) With the extensions from clap-wayland-experiment,
a submodule. Embedding uses the wayland-surface-embedding-v1 window API: the host runs a Wayland
compositor of its own, and the plugin's surface goes into the host's window through it, with the
clap_surface_embedding_v1 protocol. clap-gui-host doesn't test it yet.
Everything runs on the main thread. On Linux, the host's timer drives the GUI
(clap.timer-support);
on Windows and macOS, the window has its own timer.
The skins, one per plugin, are in skins.cc.
The plugins without a skin show a knob per parameter.
To test the hosts, the check-* plugins support only one window API and mode each, and their
GUI shows the window API, the mode, the scale and the size:
- Linux:
check-x11-floating,check-x11-embed,check-wayland-floating,check-wayland-embed - Windows:
check-windows-floating,check-windows-embed - macOS:
check-cocoa-floating,check-cocoa-embed
There is no keyboard input yet.
A CLAP plugin should be self-contained: it should not rely upon symbols from the host, and it
should export only one symbol: clap_entry.
Even if you hide all your symbols, some may remain visible at unexpected places:
- Objective-C registers every class, including those coming from plugins, in a flat namespace.
If two plugins define different classes with the same name, they clash, which results in
undefined behavior. That's why our
NSViewsubclass is created at runtime, with a name unique to the plugin's binary. - Xlib's error handlers are process-wide, a plugin would replace the host's ones. That's why we use XCB on X11.
- Wayland objects belong to a connection: the plugin opens its own one rather than sharing the host's. The host and the plugin only exchange strings, the xdg-foreign handle and the xdg-activation token, with the extensions from clap-wayland-experiment, a submodule.
You need CMake 3.21 or newer, a C++20 compiler, and the submodules:
git clone --recurse-submodules https://github.com/free-audio/clap-plugins
cd clap-pluginsThe plugins are then in builds/<preset>/plugins/Release/clap-plugins.clap.
The GUI needs libwayland-client 1.22 or newer, wayland-protocols 1.32 or newer, and libxcb,
for example Ubuntu 24.04 or newer.
# on ubuntu, adapt to your distribution and package manager
sudo apt install git ninja-build cmake pkg-config g++ libwayland-dev wayland-protocols libxcb1-dev
# on archlinux, adapt to your distribution and package manager
sudo pacman -S git ninja cmake pkgconf gcc wayland wayland-protocols libxcb
cmake --preset ninja
cmake --build --preset ninja --config ReleaseInstall the Xcode command line tools, then:
brew install cmake ninja
cmake --preset ninja
cmake --build --preset ninja --config ReleaseInstall Visual Studio 2022, with its C++ and CMake components. Then in a PowerShell:
cmake --preset vs
cmake --build --preset vs --config ReleaseThe ninja-headless and vs-headless presets build the plugins without GUI:
cmake --preset ninja-headless
cmake --build --preset ninja-headless --config ReleaseThe unit tests need Catch2 3 or newer, and
CLAP_BUILD_TESTS:
cmake --preset ninja -DCLAP_BUILD_TESTS=ON
cmake --build --preset ninja --config Release --target clap-tests
ctest --preset ninja -C ReleaseCopy clap-plugins.clap where the hosts look for plugins, for example ~/.clap on Linux,
~/Library/Audio/Plug-Ins/CLAP on macOS, or %LOCALAPPDATA%\Programs\Common\CLAP on Windows.
clap-gui-host is a minimal host, which only shows a plugin's GUI.
It prints the parameter changes.
builds/ninja/tools/gui-host/Release/clap-gui-host \
builds/ninja/plugins/Release/clap-plugins.clap com.github.free-audio.clap.synthBy default it uses the plugin's preferred window API. The options:
--x11or--wayland: the window API--floating: a floating window rather than an embedded one; Wayland is always floating. Click in the host's window to show or hide the plugin's window.--scale <factor>: the scale given to the plugin with X11. By default, like a real host, it gives the desktop's scale:Xft.dpi, or with XWayland, the ratio between the X11 screen and the Wayland outputs' logical layout. The plugins don't guess it: they use the host's. With Wayland, the sizes are logical and the host doesn't give the scale: the plugin gets it from the compositor.
Without a plugin id, it shows the gain plugin. With an unknown one, it lists the plugins.