CLAP: The New Audio Plug-in Standard (by U-he, Bitwig and others)

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

I've done the same thing with the Airwindows plugins. I'm not sure what baconpaul means when he says it's "not [a] very reasonable UX".

Post

Oh I mean "most users wanted a single plugin with all the airwindows, not to get 378 entries in their plugin ui under the airwindows category". here's the way we are doing it now https://github.com/baconpaul/airwin2rack but the underlying static library that builds could super easily make a single-clap-with-multi-plugin.

For one of my '7 plugin testbeds' I use this though and it's how we tested the wrappers too. Works great for that.

and here's the way i did it first more akin to what you have above https://github.com/baconpaul/airwin2clap

was very useful to test clap scaling though at the 0.26 point and so on but almost the first request was 'how do you not show some of these' hence the consolidated model for rack and daws.

Post

Leslie Sanford wrote: Sat Sep 07, 2024 12:20 am
In my simple delay plugin, there's only one plugin available. But I'm about to begin writing some other plugins, e.g. chorus, phase shifter, etc., and now I'm wondering if I should make them part of the same project. That's to say, the compiled CLAP file would tell the host that there are x number plugins available and create instances of them when requested by the host to do so.

Has anyone done this? How do the resulting plugins show up in the host? Are the listed as though they are separate plugins?

I can see the attractiveness of this approach. I'm creating simple free (when they're released) plugins and having a single file that gives you all of them would be kind of cool.

Thanks for any info.
Yes - I have done this as well. It's here:

https://github.com/RobinSchmidt/RobsClapStuff

just in case you need a more minimalistic example for how to do it. It's only a couple of GUI-less plugins - a sort of "AGain" example for clap. I also prefer to put all plugins into a single .dll over having a separate .dll file for each plugin because common code (like GUI framework and/or DSP library, etc.) can easily be shared among the plugins which is much more economic, especially if you have many plugins.
My plan is to put the code on GitHub if this modest attempt isn't completely embarrassing. :)
That would be great. It's always good to have a lot of code examples available to learn from. :tu:
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

Leslie Sanford wrote: Mon Sep 02, 2024 7:33 pm Has anyone had any trouble implementing a bypass parameter with Reaper?
Try their latest developer build.
We had reported a problem, and they changed something.
It's not completely fixed for us yet, but maybe your problem is solved.
That QA guy from planet u-he.

Post

tasmaniandevil wrote: Tue Sep 10, 2024 11:56 am Try their latest developer build.
We had reported a problem, and they changed something.
It's not completely fixed for us yet, but maybe your problem is solved.
Thanks for starting that thread. I've downloaded the latest developer build, and I'm still having problems. The behavior is slightly different, though. Before, every time my plugin sent a bypass on event, Reaper would immediately respond with a bypass off event. It no longer does that. However, it's not responding to my bypass change events nor is it sending bypass on events, only off events.

I'll keep an eye on that thread and may chime in.

EDIT: I see from the Reaper thread that you've solved this at the plugin level. I'm pretty sure at this point that it must be a bug on my end. I think I need to dig deeper into state management when the plugin has been bypassed. I'm looking at the start/stop callbacks as well as the flush function.

EDIT2: Got it working. I wasn't properly handling plugin state when it was offline, i.e. bypassed. I assumed that the process function would still be called in a bypass state. Once I realized that wasn't the case (duh) and properly hooked into the start/stop callbacks as well as requesting a flush in response to changing the bypass parameter in the UI, it works like a charm.

Post

Can y'all confirm that Bitwig doesn't support the CLAP_EXT_TIMER_SUPPORT extension? When I ask the host for that extension, it returns NULL at least on Windows.

Timer support is kind of a lynchpin of my plugin design. I use it for communication between the process thread and the UI thread. That's to say, if there's something that happens in the process thread that the UI needs to know about, I set the appropriate flags that are later checked in the timer callback. In turn, it sends message to the UI. This happens in reverse as well.

Is there an alternative or better approach if the timer extension is not available? I guess I could always create my own timer.

Post

We use our own timer. I think the CLAP_EXT_TIMER_SUPPORT was added for Linux support where developers can not create timers on the user thread. I could be wrong.

Post

Leslie Sanford wrote: Thu Sep 25, 2025 2:11 amThat's to say, if there's something that happens in the process thread that the UI needs to know about, I set the appropriate flags that are later checked in the timer callback. In turn, it sends message to the UI. This happens in reverse as well.
I assume there's some reason the process thread doesn't just call host->request_callback() and then check the flags in plugin->on_main_thread(). Is it because you could be getting these events every block, but want to batch your UI messages so they're only every 15-30ms or something?

Post

signalsmith wrote: Thu Sep 25, 2025 10:34 am I assume there's some reason the process thread doesn't just call host->request_callback() and then check the flags in plugin->on_main_thread(). Is it because you could be getting these events every block, but want to batch your UI messages so they're only every 15-30ms or something?
I confess I didn't know about host->request_callback() until last night when going through CLAP's header files again. I should've known the on_main_thread callback was there for a reason! :oops:

But, yeah, I need to make sure when I switch over to using it, I don't spam the host with requests. I'll give this some thought.

Post

More Bitwig problems. :)

My flush callback isn't getting called when running my plugin on Bitwig. This relates specifically to my plugin's bypass parameter, the one configured with the CLAP_PARAM_IS_BYPASS flag.

In Reaper, the sequence of events when clicking the bypass control (unchecking a checkbox) on the Host's UI seems to be:
  • Host stops processing.
  • Host calls the plugin's flush callback passing it a parameter event corresponding to the plugin's own bypass parameter.
This keeps the plugin state in sync with that of the Host.

When turning off bypass mode via the Host's UI (checking the checkbox), the Host resumes processing and sends a parameter event (corresponding to the plugin's bypass parameter) to the process callback.

These events don't seem to occur with Bitwig. If I click the enable/disable button on the Host, nothing happens. The flush callback isn't invoked when disabling the plugin and no parameter event is sent to the process function when the plugin is re-enabled.

This problem occurs when bypassing the plugin using the plugin's UI as well. I can't seem to get the bypass parameter to take on Bitwig like I can on Reaper.

Is there another flag in addition to CLAP_PARAM_IS_BYPASS that I should be using for my bypass parameter? Is there something else I'm overlooking?

Post

For what it's worth, I also didn't have CLAP_EXT_TIMER_SUPPORT in Bitwig on Windows, only on Linux.

Post

Alien Brother wrote: Thu Sep 25, 2025 11:01 pm For what it's worth, I also didn't have CLAP_EXT_TIMER_SUPPORT in Bitwig on Windows, only on Linux.
yeah so, right or wrong, the intent with the timer support was to allow timers on oses which don't have a main thread concept.

On win and mac the OS provides a main thread so most of us use CFTimerBlah and the windows equivalent or its wrap in juce::MessageManager or whatever you get on your plugin platfor

On X11 there is no "message thread" in the same way as mac and windows. Without comment as to that being good or bad, it does mean there is no os way to schedule a callback event on your UI thread in the os level (more or less if you want to disagree with this mildly hand-wavy characterization based on details then lets not clutter up this thread). So to make UIs work on linux you need some way to schedule on whichever thread the host thinks is your UI thread and another way to subscribe to file handle callbacks.

Since writing it several folks have asked why it's not supported on win/mac. This is why, but there's no real reason that bitwig or other hosts couldn't proxy it to CFTimer or whatever I don't think; just they dont because its a feature who at its origin was really designed to make Linux UIs work.

Hope that helps

Post

Are CLAP plugins always single files or can they also have a folder structure like vst3 or lv2? I ask because I was testing one distributes in the latter. It works but every other clap plugin I have is in a single binary.

Post

Largos wrote: Wed Oct 29, 2025 12:46 pm Are CLAP plugins always single files or can they also have a folder structure like vst3 or lv2? I ask because I was testing one distributes in the latter. It works but every other clap plugin I have is in a single binary.
There is nothing in the CLAP standard that specifies how or where a folder structure should be organized. Those are conventions set by the OS for loading libraries.

On a Mac, a .clap file is a package, that is, a folder structure that presents itself as a single file. A certain structure of folders and metadata in that package is required by the OS. VSTs, AU Components, and VST3 plugins all follow this same standard. As part of that standard other resources may be included as well, such as unchangeable factory presents. But that's up to the plugin developer, not the CLAP standard itself.

Most plugins will put additional data in the standard locations specified by the OS. On a Mac, this would be in ~/Library and/or /Library under "Application Support" and "Preferences"

Sometimes a plugin package on a Mac will be missing a BNDL identifier, which is contained in the Contents/PkgInfo file. This will make the plugin appear as a folder rather than a single file. But it will still load correctly.

Post

teilo wrote: Wed Oct 29, 2025 4:11 pm Sometimes a plugin package on a Mac will be missing a BNDL identifier, which is contained in the Contents/PkgInfo file. This will make the plugin appear as a folder rather than a single file. But it will still load correctly.
Yeah, the "bundles" are pretty much just a Finder thing and Finder looks at the Contents/PkgInfo (if any) to see if it should display it as a bundle. You can still access it as a directory too though, you just need to right-click and pick "Show package contents" from the context menu. Other than Finder though (eg. on the command line) they are always just normal directories really.

The important file that needs to be there though is Contents/Info.plist which among other things tells the host the actual filename of the plugin binary (within the bundle) that should be loaded.

Post Reply

Return to “DSP and Plugin Development”