Skip to content

Instantly share code, notes, and snippets.

@abique
Last active November 17, 2022 10:58
Show Gist options
  • Save abique/4c1b9b40f3413f0df1591d2a7c760db4 to your computer and use it in GitHub Desktop.
Save abique/4c1b9b40f3413f0df1591d2a7c760db4 to your computer and use it in GitHub Desktop.
Proprietary Audio Plugins for Linux, but the right way

Proprietary Audio Plugins for Linux, but the right way

Why the current approach to VST and VST3 does not work for proprietary plugins on Linux ?

When building plugins for Linux there are two options and one problem:

  1. Link to the system libraries
  2. Build all your dependencies and statically link to them
  3. Can't use gtk or qt.

What's wrong with solution 1.?

  • It forces to build using an old system in order to maintain a maximum level of compatibility. Which prevents from using modern compiler and library features.
  • There is no guarentee that the plugin will load on the user system.

What's wrong with solution 2.?

  • It requires work to maintain your development libraries, some might not even be working on the user system (paths with fontconfig?, configuration files format change, ...).
  • More work to ensure maximum compatiblity toward libm, libc, ...
  • The host will probably use dlopen(RTLD_LOCAL), because RTLD_DEEPBIND creates various issues, breaks most plugins and is not used in the end. RTLD_LOCAL means that the plugin will use the symbols from the host before its own, which might turn out to be bad for multiple reasons. While if everyone uses the symbols from the system's runtime there is no conflict at all. One problematic scenario is:
    • host is staticaly linked against libX version N
    • plugin is dynamicaly linked against libX version N+1
    • libX_blah_create() returns an opaque pointer libX_ptr, which has a different data layout in version N+1
    • libX_doY(libX_ptr) is a new symbol introduced in version N+1 which takes this opaque pointer as argument; unfortunately in our case it was allocated by libX_blah_create() from version N, but then used by the symbol libX_doY() from version N+1 which expects a different data layout -> BOOM

Does a plugin wants Gtk or Qt? And why?

Yes absolutely! And, this is the biggest problem. This is so big that it is unrealistic. Right now a plugin needs to go through a huge pain in order to show a GUI. The reason why it can't use gtk or qt, is because those don't behave well when mixed together. And imagine multiple version being mixed together having symbols clash...

The consequence is that the plugin developper will use xcb, cairo, and basically write their own toolkit in order to display a knob. No one wants to write a GUI toolkit in order to write a plugin.

My proposal

  1. Be able to run the plugins in their own process.
  2. Plugin may not use an ABI but a protocol involving IPC.
  3. There should be a registry of all the plugins available, to which you can communicate and create instances of a plugin.

How to realize it?

I will focus on the idea that DAWs an plugins will be distributed via flatpak and linked to its runtime. Obviously it does not make flatpak a requirement but instead forces the design to work across sandboxes and runtimes.

Plugins and DAWs may be linked statically or against a flatpak runtime, it does not matter as they will be isolated from each others.

Then, we need the plugin registry.

  • it must be reachable from any sandboxes
  • it must be able to index plugins available on the system and installed via flatpak
  • it must be able to spawn plugin processes and establish IPC between the DAW and plugins

A proprietary plugin can:

  • Link dynamically against (system|flatpak)'s runtime or link statically
  • Use GTK or Qt (or whatever they like)
  • Be distributed via flathub
  • Be used by a DAW built against a different runtime

The plugin and daw can still implement vst2, vst3, lv2, ..., and it would be implicitely wrapped by a transparent host doing the daw <-> vst3 <-> bridge/plugin <--- IPC ---> bridge/host <-> vst3 <-> plugin.

We don't want to impose to the industry to support a new plugin api.

This will let a DAW sandboxed and started using runtime Y to use plugins from the system or even built for an other flatpak runtime.

In the end this work will turn Linux into a top level place for multimedia processing:

  • Painless GUI using gtk/qt or whatever.
  • Easy to develop
  • Easy to debug
  • Easy to distribute and get visibility in Flathub
  • Easy to get a working system and stable system for the user
  • Preserve user's freedom and control by linking dynamically to the flatpak runtime: the user has control over his runtime
  • Preserve user's security by having different sanboxing parameters for each plugins and daw. Otherwise the DAW must have the maximum permissions requirements from each plugins, and it each plugins would inherit the daw's permissions which is not what we want, for example we may want to disable network access for most audio plugins.

Reducing IPC overhead

The overhead comes from context switching between processes, and the smaller the latency is (undestand audio interface buffer size) the higher the overhead becomes.

The solution is to bulk process.

Let's take a concrete exemple:

  • DAW is using runtime X
  • N plugins from the same vendor We could create a single plugin process for multiple plugins from the same vendor. That way, when the host host can group the processing requests toward nultiple plugins into one single bulk request, reducing the amount of context switch.
@plaimbock
Copy link

Hello,
We just released Bitwig 3.3.1 Beta 1, and this time we used dynamic linking against the system runtime for the most common libraries that we use and it works much better, I think it resolved all our plugin hosting problems related to dynamic linking. But on the other hand we now require Ubuntu 18.04 or newer.
Regards,
Alexandre

Hi Alexandre, I'm happy to report that the Audio Damage Continua, Venomode Phrasebox and Vital plugins no longer crash on Fedora 33. Thanks!

@tank-trax
Copy link

tank-trax commented Dec 9, 2020

Operating System: Debian GNU/Linux 10
KDE Plasma Version: 5.14.5
Qt Version: 5.11.3
KDE Frameworks Version: 5.54.0
Kernel Version: 5.9.1-rt20avl1
OS Type: 64-bit
Processors: 4 × Intel® Core™ i5-3470 CPU @ 3.20GHz
Memory: 11.4 GiB of RAM

Surge typeins work and both Vital VST3/VST2 load optimally without crashing using the new bitwig-studio-3.3.1beta1 version

also tested a bunch of VST3 and VST2 plugins, both open source and proprietary and all load and play without issue

looks like there are no longer any intermittent black screen issues with VST3 plugins

However after verifying in Synaptic the system was broken due to missing dependencies and it had to be removed

reinstalling provided this clue...

dpkg -i bitwig-studio-3.3.1beta1.deb 
Selecting previously unselected package bitwig-studio.
(Reading database ... 567387 files and directories currently installed.)
Preparing to unpack bitwig-studio-3.3.1beta1.deb ...
Unpacking bitwig-studio (3.3.1beta1) ...
dpkg: dependency problems prevent configuration of bitwig-studio:
 bitwig-studio depends on libxcb-util1; however:
  Package libxcb-util1 is not installed.
 bitwig-studio depends on libxcb-util1:i386; however:

dpkg: error processing package bitwig-studio (--install):
 dependency problems - leaving unconfigured
Processing triggers for desktop-file-utils (0.23-4) ...
Processing triggers for mime-support (3.62) ...
Processing triggers for hicolor-icon-theme (0.17-2) ...
Processing triggers for shared-mime-info (1.10-1) ...
Errors were encountered while processing:
 bitwig-studio

the good news is installing libxcb-util1 for Bullseye (Testing), in my case libxcb-util1_0.4.0-1+b1_amd64.deb and libxcb-util1_0.4.0-1+b1_i386.deb, resolved the issue for Buster

so far no crashes, will report back if any occur that I can trace to having both libxcb-util0 and libxcb-util1 on the same system

in case this is helpful for Debian Buster

/usr/lib/x86_64-linux-gnu$ ls -l libxcb-util*
lrwxrwxrwx 1 root root    20 Aug 26  2014 libxcb-util.so -> libxcb-util.so.0.0.0
lrwxrwxrwx 1 root root    20 Mar  5  2020 libxcb-util.so.0 -> libxcb-util.so.0.0.0
-rw-r--r-- 1 root root 26936 Aug 26  2014 libxcb-util.so.0.0.0
lrwxrwxrwx 1 root root    20 Nov 28 07:13 libxcb-util.so.1 -> libxcb-util.so.1.0.0
-rw-r--r-- 1 root root 26856 Nov 28 07:13 libxcb-util.so.1.0.0

/usr/lib/i386-linux-gnu$ ls -l libxcb-util*
lrwxrwxrwx 1 root root    20 Aug 26  2014 libxcb-util.so.0 -> libxcb-util.so.0.0.0
-rw-r--r-- 1 root root 22032 Aug 26  2014 libxcb-util.so.0.0.0
lrwxrwxrwx 1 root root    20 Nov 28 07:12 libxcb-util.so.1 -> libxcb-util.so.1.0.0
-rw-r--r-- 1 root root 26080 Nov 28 07:12 libxcb-util.so.1.0.0

As an addendum

in Bitwig 3.2.4 Vital and Surge work and in Bitwig 3.2.5 Vital works and Surge crashes
in bitwig-studio-3.3beta5 Surge works and Vital crashes
could not test in prior 3.3 beta versions as the update to 3.3 was recommended and Bitwig would shut down
if not mistaken, in in bitwig-studio-3.3beta4 Surge would crash and Vital would not

this discussion in Facebook Bitwig Linux Group mentioning that there was an issue with U-He plugins that could not get window focus around the time of 3.2.4 -> 3.2.5 may prove useful

@KottV
Copy link

KottV commented Dec 10, 2020

Regarding pipewire, I don't understand what your concern is,

I'm just skeptical grumpy about that. As about wayland too )

@abique
Copy link
Author

abique commented Dec 10, 2020

Regarding pipewire, I don't understand what your concern is,

I'm just skeptical grumpy about that. As about wayland too )

There is an equivalent to xembed for wayland: you have to provide a full wayland compositor channel to the plugin.
It is not a problem if you are using gtk or qt, because they provide the necessary API to make this task simple, but if you have to write it yourself... then there is a lot of work and room for bugs.
If the plugin host has to use gtk or qt, it will make dlopening() plugin even more problematic.

I'm still convinced that the right approach is:

  • link against flatpak runtime
  • use plugins via IPC

@tank-trax
Copy link

tank-trax commented Dec 11, 2020

I tried the FlatPak version of Ardour 6.5

A few things I noticed

  • there was only ALSA and Pulse and no JACK support
  • Ardour was able to navigate to the $HOME folder but not outside the container for example to 2nd Hard Drives
  • a significant proportion of VST2 and VST3 instruments and effects got blacklisted, of note is that all the u-he Synths loaded (I figure the fails were due to missing libraries in the container)
  • could play two MIDI tracks with two controllers and two individual synths using ALSA mode

My initial reaction to your proposal was skepticism but after reading more about FlatPak and Pirewire I am intrigued. That being said the hurdles to get such an environment to work in real time without additional audible artifacts I would think may be considerable.

I disagree with this notion though

But if a plugin crash, there is nothing that can be done. Better to be slow than to crash.

If a plugin crashes I would think that determining the reason and resolving should not be at the expense of or to make compromises on latency or CPU and RAM time. As a user that can be a deal breaker.

My hunch though is that your idea could work if the containers are limited.... possibly one container for all plugins and then individual containers for each plugin host, but admittedly the technical aspect is outside my scope. Would like to test out any trial runs should the time arise or when and if Bitwig has a FlatPak version.

@x42
Copy link

x42 commented Dec 15, 2020

I tried the FlatPak version of Ardour 6.5

Keep in mind that this is provided by a 3rd party and Ardour developers do not recommend to use it.

@takuvata
Copy link

takuvata commented Jan 8, 2021

You maybe missed the design? Of course it does not work for VST3 as it is.

Could you explain how exactly it does not work? I built Bitwig Studio 3.3.1 flatpak for myself and tested with VST3 Surge as it is currently shipped via Flathub - works perfectly fine. Just like all the other lxvst plugins.

they're all in the same location (/app/extensions/Plugins/vst3) not separated, nor using individual libraries per plugin.

My understanding here might be limited, but I think paths /app/extensions/Plugins/{lxvs,lv2,vst3} are just the way flatpak's extension is presenting it. Real plugin paths are at the level above, like for Surge it is: /app/extensions/Plugins/Surge/ where it can have it's own lib dir.

It's a pipedream to think that flatpak will solve any issues for plugin distribution.

Well, for me, as a user who actually wants to use software and not spend hours and days hunting down information on how to install it - it very much solves, very real problem. Using flatpak I can actually install things and those things work. I can install Ardour via flatpak and even though it's unofficial and not-recommended way to use it - I have much better experience with that, than using any other way. I use Fedora as my distribution of choice and if not for flatpak and the fact that there's a decent collection of audio plugins available through it - applications like Ardour or lmms would be pretty much useless to me. Fedora doesn't package lots of plugins, developers do not package for Fedora, so as a user I am supposed to do what? Build from source? Use some other distribution? That's what I call a horrible user experience.

Instead of adding more abstraction and wrappers, we need to prevent the issue from happening in the first place.

I'm afraid that ship has sailed a long time ago. To prevent the issue from happening in the first place people should have not been churning out different incompatible Linux distributions like there's no tomorrow over the past 30 years or so. However that's just a nature of the beast.

In Flatpak I see a tiny bit of hope. It was easier for me to build (more correctly - repackage, in this case) a flatpak of the Bitwig Studio, once I found the git repo for it, than to get some plugins working in a non-flatpak way. I have been using Linux as my primary operating system for almost two decades now and if it is true that things like Flatpak will not solve anything - I'll have to conclude that Linux as a desktop operating system is truly doomed.

@abique
Copy link
Author

abique commented Jan 8, 2021

You maybe missed the design? Of course it does not work for VST3 as it is.

Could you explain how exactly it does not work? I built Bitwig Studio 3.3.1 flatpak for myself and tested with VST3 Surge as it is currently shipped via Flathub - works perfectly fine. Just like all the other lxvst plugins.

If the DAW and plugin are built for different runtimes, they won't be able to see each other and there is no dlopen() which could work. That's why they need to run in their own process and then we need to establish a communication pipeline (likely shm + semaphore). And finally the plugin being its own process is easier to debug and can use all the libraries it wants (qt or gtk).

@takuvata
Copy link

takuvata commented Jan 8, 2021

If the DAW and plugin are built for different runtimes, they won't be able to see each other and there is no dlopen() which could work

Ah, I see. That clears things - thanks.

@baconpaul
Copy link

I built Bitwig Studio 3.3.1 flatpak for myself and tested with VST3 Surge as it is currently shipped via Flathub - works perfectly fine

There's a flathub distribution of surge out there?

@takuvata
Copy link

takuvata commented Jan 9, 2021

There's a flathub distribution of surge out there?

Oh yes - org.freedesktop.LinuxAudio.Plugins.Surge. Works perfectly fine for me.

@tank-trax
Copy link

Oh yes - org.freedesktop.LinuxAudio.Plugins.Surge. Works perfectly fine for me.

@baconpaul here it is...

@abique
Copy link
Author

abique commented Apr 15, 2021

@baconpaul @takuvata I don't understand how it currently works.

flatpak search vst3
Name                      Description                                                        Application ID                                              Version          Branch       Remotes
DISTRHO-Ports             DISTRHO Plugin Ports LV2/VST/VST3                                  org.freedesktop.LinuxAudio.Plugins.DISTRHO-Ports            2021.03.15       20.08        flathub
sfizz                     sfizz is a sample-based musical synthesizer LV2/VST3 plugin        org.freedesktop.LinuxAudio.Plugins.sfizz                    0.5.1            20.08        flathub
sfizz                     sfizz is a sample-based musical synthesizer LV2/VST3 plugin        org.freedesktop.LinuxAudio.Plugins.sfizz                    0.4.0            19.08        flathub
WhiteElephantAudio        White Elephant Audio VST3 plugins                                  org.freedesktop.LinuxAudio.Plugins.WhiteElephantAudio       2021.03.05       20.08        flathub
Surge Synthesizer         Surge Synthesizer LV2/VST3                                         org.freedesktop.LinuxAudio.Plugins.Surge                    1.8.1            20.08        flathub
Surge Synthesizer         Surge Synthesizer LV2/VST3                                         org.freedesktop.LinuxAudio.Plugins.Surge                    1.7.1            19.08        flathub
Dexed                     Dexed FM Synthesizer VST/VST3 plugin                               org.freedesktop.LinuxAudio.Plugins.Dexed                    0.9.6            20.08        flathub
Dexed                     Dexed FM Synthesizer VST/VST3 plugin                               org.freedesktop.LinuxAudio.Plugins.Dexed                    0.9.5            19.08        flathub

Can a DAW from the system use them?
Can a DAW using a different runtime use them?

@abique
Copy link
Author

abique commented Apr 15, 2021

@abique
Copy link
Author

abique commented Apr 15, 2021

@baconpaul
Copy link

@abique - No idea!
@tank-trax - can you help out?

@tank-trax
Copy link

tank-trax commented Apr 15, 2021

just installed Bitwig Flatpak (on a non-Audio dedicated workstation) and will see if I can get it to recognize plugins

so far it recognizes the two synths that are located in ~/.vst3

am installing Surge via flatpak install flathub org.freedesktop.LinuxAudio.Plugins.Surge//20.08

this is cool. it connects audio using ALSA directly...

the problem as I suspected is the plugins have their own container and Bitwig can only navigate in two locations

User and its System... which is not the System's System...

Flatpak Surge is installed in

/var/lib/flatpak/runtime/org.freedesktop.LinuxAudio.Plugins.Surge/x86_64/20.08/active/files/

there is no way to navigate to this location as it is outside Flatpak Bitwig's container

in my opinion to get this to work... all plugins would have to be in the same container.... which defeats the purpose of this experiment as it would require all plugins within this container to use the same runtime...

possibly symbolic links could work but this is an ugly hack and not really a solution (in my opinion)

this Flatpak limitation would also render all plugins in /user/lib/vst3 and /usr/local/lib/vst3 outside of Flatpak Bitwig's reach

@tank-trax
Copy link

tried a symbolic link and no dice... I would conjecture that Flatpak Bitwig will only be able to detect Surge if and only if it is a local install and not Flatpak

not optimistic about Flatpak DAWS and Flatpak plugins being able to work together...

for example with WINE... all the plugins are either in the WINE folder or accessible to locations outside the WINE container... with Flatpak each plugin is in its own container... which is not in the DAW container... this is problematic

@abique
Copy link
Author

abique commented Apr 15, 2021

Is bitwig and surge sharing the same runtime?
Maybe you need to add a location for the plugin?

I'll look into it later.

@tank-trax
Copy link

Bitwig is located here

/var/lib/flatpak/app/com.bitwig.BitwigStudio/x86_64/stable/6267badf04b6977108cfb068cedc00b8dae9d57e80c671c0db488088f54f831b/files/

Surge is located here

/var/lib/flatpak/runtime/org.freedesktop.LinuxAudio.Plugins.Surge/x86_64/20.08/7464c5cd5222d0d0228a8788ad6ff3bbf625429b43d7d67f5479dccce1e70cdb/files/

as far as I understand how plugins work they have to run within the Host... I am really not sure how this is supposed to work with Flatpak... the plugins would have to be inside the Host's container... as plugins do not execute

I would think there would need to be a universal runtime layer or container... one that acts as a go between the DAW of choice and every other plugin in the Flatpak ecosystem as each and every one of them will be in their own unique Silo and locked down System/Container

@tank-trax
Copy link

noticed that you starred this

will try this and get back... which runtime is Bitwig? does it matter?

@jarkkojs
Copy link

jarkkojs commented Apr 16, 2021

Perhaps unorthodox idea, but why not build tailored Wine to the DAW? Like Steam does for games.

I personally use Windows versions even of the plugins for which there is a Linux version, just because it management wise easiest way to get shit done (when producing music). Other options is to have ~/.wine, ~/.vst, ~/.vst2 and what not.

All platforms considered it would be cool if plugin industry would give a shot doing something similar Sun tried to do years back with PWI (Public Windows Interface). It was a failure but in audio plugin it could work out. I.e. standardize a subset of Windows API that plugins would use. That could even mean ABI compatibility for plugin binaries using the same ISA

I.e. instead of macOS, Windows and Linux version of a plugin you'd just have ARM, x86 etc. versions

Plugins are in the just huge calculators with an UI, pretty simple stuff, when you think it that way. I/O wise they are most of the part as simple as Minesweeper game.

Plugin API's do not need any change. What is needed is a standard PRE (Plugin Runtime Environment) :-)

@takuvata
Copy link

@tank-trax:

there is no way to navigate to this location as it is outside Flatpak Bitwig's container

From flatpaked Bitwig's perspective flatpaked plugins are in /app/extentions/Plugins/vst3 and /app/extentions/Plugins/lxvst. Need to add those paths in Bitwig's Settings->Locations. Not configured by default. Those paths are internal container paths.

@abique:

Can a DAW from the system use them?
Can a DAW using a different runtime use them?

You cannot use flatpaked plugins from non flatpak application. Each plugin extends linuxaudio base runtime which in turn extends freedesktop.org runtime and they all see those paths I mentioned earlier within the container's filesystem. I think you can use those plugins in any DAW that is built against the runtime which extends freedesktop.org runtime, for example gnome runtime, KDE runtime, or your own custom runtime as long as that custom runtime extends freedesktop.org runtime and in flatpak manifest it adds org.freedesktop.LinuxAudio.Plugins extention.

I do not remember exact technical reason why that linuxaudio extention was needed, though. Github user @hfiguiere is the creator of that extension and the most active maintainer, probably he could explain all this much better than me.

@abique
Copy link
Author

abique commented Apr 27, 2021

I think it is going to work well with flatpak with traditional plugin loading. Let us see.

@takuvata
Copy link

@tank-trax

it connects audio using ALSA directly...

Btw, when using pipewire (default on latest Fedora) you can also use JACK as audio subsystem in Bitwig without needing to have actual JACK installed (real JACK will not work in flatpaked apps)

@hfiguiere
Copy link

You cannot use flatpaked plugins from non flatpak application. Each plugin extends linuxaudio base runtime
[...]
I do not remember exact technical reason why that linuxaudio extention was needed, though. Github user @hfiguiere is the creator of that extension and the most active maintainer, probably he could explain all this much better than me

Not exactly. The thing with extension is that they need:

  1. an extension point which determine what they are and where there are in the container - it is also important the filesystem mount point exists even to build.
  2. a SDK to be build against

Typically an extension is specific to an app. Like a plugin for GIMP.
In that case, as we know, it's not, it just implement an API. Still it needs the two. So that "BaseExtension" app is only used to:

  1. specify the extension point (like the application using it do)
  2. specify a SDK, in that case the freendesktop-sdk, used to build it.

Note that the extension doesn't specify the SDK. The application does. Freedesktop-sdk is the baseline for both the GNOME and KDE runtime, so either can be used by the app.
There is no check performed.

The BaseExtension is just an empty shell.

@hfiguiere
Copy link

Just to add, when I say no check is performed, the only check is that the version specified in the app add-extension object is matched against the branch for each extension.

version: '20.08' will get the extension from the //20.08 branch. But here nothing prevent an extension from being build against a different runtime, but it's just looking for trouble.
versions can specify multiple versions, but there is currently only a 20.08 branch.

Also the runtime matter much less if is no build (ie packaging from binaries)

@hfiguiere
Copy link

Btw, when using pipewire (default on latest Fedora) you can also use JACK as audio subsystem in Bitwig without needing to have actual JACK installed (real JACK will not work in flatpaked apps)

The current Flatpak for Bitwig should work with Pipewire when using JACK, provided that Pipewire on the host also work (Fedora 34 for example). Any further trouble is linked to Pipewire, one notable issue being setting real-time priority.
It failed when the package was reviewed because of the bug in the runtime that has since been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment