Framework
DISTRHO/DPF avatar
DISTRHO/DPF

DPF: exporting six plugin formats from one C++ codebase

DISTRHO Plugin Framework

878 stars125 forksC++ISC

At a glance

What is it?
DPF is a C++ plugin framework that writes the DSP and UI once and then exports LADSPA, DSSI, LV2, VST2, VST3 and CLAP from the same sources, with a JACK standalone mode for quick testing. The trade-off is that each format's feature coverage differs, and FEATURES.md is where you find out which ones.
Who is it for?
DPF suits plugin authors who want to ship several plugin formats from a single C++ implementation, especially while testing in the JACK standalone mode, and the ISC licence keeps commercial use straightforward. It is the wrong choice for a plugin that depends on a format specific extension such as DSSI's unique state handling, since internal state storage breaks that compatibility.
Can I use it commercially?
Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One plugin implementation, six exported formats

Writing a plugin for a modern host usually means choosing one format, learning one SDK, and shipping one binary. The alternative is to maintain a separate implementation per format, which multiplies the work of every bug fix and every UI tweak. DPF exists to collapse that multiplication.

The framework is written in C++ and is described as a way to build plugins with custom UIs through a simple C++ API, and the payoff is that the same code base can be exported to LADSPA, DSSI, LV2, VST2, VST3 and CLAP. A plugin author writes the processing once and the build produces the format specific artefacts from it. The repository also carries a JACK and standalone mode, which the documentation presents as a way to test plugins quickly without going through a full host.

The people this is written for are plugin developers, not host developers. The repository points to a wiki page listing plugins made with DPF, and to a folder of example plugins inside the repository itself, so the intended learning path is to read a working example rather than to follow a long tutorial. The framework is deliberately narrow in scope: it handles the plumbing between a host and your code, and it leaves the audio design to you.

The UI talks to the DSP side through key-value pairs

The mechanism that makes a custom UI portable across six formats is the communication channel, and DPF's version of it is deliberately plain. Plugin DSP and UI communication is done via key-value string pairs. A control in the UI sends a message to the DSP side, and when required the framework saves that value in the host automatically.

That last clause carries most of the weight. If the parameter change is routed through the framework's message mechanism, the host's own state saving captures it, so a user who saves a preset or closes the session gets consistent behaviour without any state serialisation code written by hand. The design keeps the parameter plumbing as strings rather than as a typed channel, which is easy to read and easy to log, and it means one UI code path serves every exported format.

Host time information is also reachable. The documentation states that getting time information from the host uses the same format as the JACK Transport API, and it points out the practical benefit of that choice: some code ports more easily because the time representation already matches what JACK code expects. For tempo-synced effects, that removes a class of conversion you would otherwise write for every format.

Storing state internally is the DSSI compatibility breaker

There is one explicit caveat in the communication design, and it is worth reading twice before you design a plugin around internal state. The documentation notes that you can store state internally if needed, but that doing this breaks DSSI compatibility.

The reason follows from the previous section. Automatic saving in the host happens because the DSP side received the value through the key-value channel, so the host knows about it. A value that only ever lives inside your own code is invisible to the host, and a format such as DSSI, which expects the host to own state handling, will not see it. The symptom is not a build error or a crash but a plugin that appears to forget its settings.

This is a genuine design boundary rather than a bug. Any feature that needs state the host cannot know about, custom internal caches, cross-parameter derived values, and the like, has to be expressed in a way that keeps the host in the loop, or the plugin ships with a DSSI format that misbehaves. The documentation does not enumerate which features have this constraint, so the practical approach is to keep state in the framework's channel by default and treat internal storage as an explicit, format-aware decision.

The top level Makefile builds the library and the examples

The build is driven by a plain make workflow at the repository root. The file begins with a shebang that selects make and includes a shared base file:

bash
#!/usr/bin/make -f

From there, the default target of that Makefile is spelled out as three goals, which tells you what a build from a clean checkout produces: the DGL library, the example plugins, and a generation step.

bash
all: dgl examples gen

The examples goal is not a single blob. It recurses into individual example directories, so you can build one plugin on its own, and the recursions are guarded by feature checks. The CVPort, FileHandling, Info, Latency, Meters, Metronome, MidiThrough, Parameters, SendNote and States examples are built unconditionally, while CairoUI only builds when the environment reports Cairo support:

bash
ifeq ($(HAVE_CAIRO),true)
	$(MAKE) all -C examples/CairoUI
endif

Two more examples, EmbedExternalUI and WebMeters, sit behind the DGL check, and the DGL library itself is only built when the same condition holds. In other words, the repository ships examples that require optional dependencies and the build system quietly leaves them out when those dependencies are missing, rather than failing the whole build. If you are targeting a machine without Cairo or DGL, those two example plugins are not what you get, and you should check the flags before assuming a missing binary is a build problem on your side.

Two example features are switched on for the build

The top level Makefile exports a couple of environment variables that only some of the examples need, and they are a useful hint about what the example set covers. Both are set to true at the top of the file:

bash
export USE_FILE_BROWSER = true
export USE_WEB_VIEW = true

The first corresponds to the FileHandling example and the second to the WebMeters example, which embeds a web view. That web view is only available when the DGL library is present, which is the same condition that gates the WebMeters build, so on a system without DGL the variable is harmless: no example that needs it is compiled.

The generation target is similarly conditional. Whether it runs at all depends on the cross compiling flag, and the generation step itself needs a helper binary built first:

bash
gen: examples utils/lv2_ttl_generator
	@$(CURDIR)/utils/generate-ttl.sh

The helper is built by a second make invocation into the utility directory, and the script is then run from the repository root. This produces TTL files for LV2, which is the kind of artefact a host needs to discover and describe an LV2 plugin. When the build is cross compiling, the generation step is disabled unless an executable wrapper is configured, because the generated files would otherwise reflect the target platform rather than the build machine. If you are cross compiling for an embedded target, expect the LV2 metadata to be missing unless you supply that wrapper.

FEATURES.md is the real specification of what works

Anyone evaluating DPF for a specific format will find that the project directs them to a file rather than to a feature list on the front page. Provided features and implementation status for specific plugin formats can be seen in FEATURES.md, and the top level file list shows it sitting next to the licence documentation and the build files.

That is the honest way to read this project. A framework that promises six output formats cannot offer the full feature set of every host SDK in every format, so some capability will be missing in some of them, and the only way to know which is to read the per format table. The same caution applies to the format list itself: LADSPA, DSSI, LV2, VST2, VST3 and CLAP are all build targets, but buildable is not the same as feature-complete, and the framework's own documentation treats the difference as something to look up rather than something to assume.

The examples double as the detailed specification. There are fifteen example directories covering control voltage input, Cairo drawing, embedded external UIs, file handling, information output, latency reporting, meters, a metronome, MIDI passthrough, parameters, note sending and state handling. Each one exists to demonstrate a specific mechanism you would otherwise have to discover from the headers.

ISC licensing, with format specific caveats

The licence is ISC, and the project states the practical meaning plainly: you can do whatever you want as long as you credit the original authors. For a plugin framework used to ship commercial instruments, that is a permissive and uncomplicated starting point, and it also means the framework itself can be vendored into a proprietary plugin build without a separate commercial negotiation.

The caveat is in the second half of the licensing section. Some plugin formats may have additional restrictions, and the project points to a separate LICENSING.md file for details. This is a real distinction in the plugin world. A format can be an open specification while the SDK or the branding around it carries terms that the framework licence cannot override, so the DPF licence only settles the framework side of the question. Read LICENSING.md before you commit to shipping a binary in any particular format, and treat the framework licence as necessary but not sufficient.

The repository also shows a history of care about the boundary between the two. Beyond LICENSING.md, the project keeps FEATURES.md for per format status, a Doxygen configuration file for the API documentation, a dpf.kdev4 project file for KDE users, a separate tests directory, and a cmake directory alongside the make based build, so there is more than one supported way to build and check the code.

Editorial conclusion

DPF suits plugin authors who want to ship several plugin formats from a single C++ implementation, especially while testing in the JACK standalone mode, and the ISC licence keeps commercial use straightforward. It is the wrong choice for a plugin that depends on a format specific extension such as DSSI's unique state handling, since internal state storage breaks that compatibility. Before you start, read FEATURES.md for the exact list of implemented features per format, check LICENSING.md for format specific restrictions beyond ISC, and confirm that the example plugin you intend to copy builds with your toolchain, because the top level Makefile compiles the DGL library and the examples through separate make targets.

Frequently asked questions

Which plugin formats can DPF build?

DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP, and a JACK and standalone mode is also available for quick testing. The provided features and implementation status for each format are listed in FEATURES.md.

How does DPF pass parameter changes between the plugin UI and the DSP code?

Communication happens through key-value string pairs, where the UI sends a message to the DSP side and the framework automatically saves it in the host when required. You can also store state internally, but the documentation notes that this breaks DSSI compatibility.

How do I build the DPF examples?

The top level Makefile drives the build, with a default target that builds the DGL library, the examples and a generation step. The example targets are built one directory at a time, and some of them are conditional on the Cairo and DGL checks being true.

What licence does DPF use?

DPF is released under ISC, which the project describes as allowing you to do what you want as long as you credit the original authors. Some plugin formats may carry additional restrictions, and the project points to LICENSING.md for those details.

Official sources

  1. DISTRHO/DPF on GitHub
  2. Issues
  3. License: ISC
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/distrho-dpf.svg)](https://hysenlabs.com/projects/distrho-dpf)

Was this useful?