lv2_ui.h
The LV2 user interface.
#include <sonore/lv2_ui.h>- 5types
- 15other declarations
- Guides: Getting started, Platforms and formats
On this page
Design notes
The same WebView page that CLAP, VST3 and AU show, presented the way LV2 asks for it. Without this an LV2 host draws a column of generic sliders and the plugin the seller designed simply does not appear.
LV2 keeps the interface and the DSP FURTHER APART than any other format here. They are separate objects with separate lifetimes, they may be in separate binaries, and a host is entitled to run them in separate PROCESSES. So this shares no state with the plugin instance: everything the interface knows arrives through port_event(), and everything it does leaves through the host's write_function. That is more restrictive than the CLAP path, which reaches into the instance directly, and it is the reason this is a separate file rather than a branch inside the wrapper.
WHAT IS HERE, and what is not:
Windows (ui:WindowsUI): complete, and tested by embedding it in a real
window and driving a real message loop, exactly as the CLAP and VST3
GUI tests do.
X11 (ui:X11UI): NOT built, and the reason is worth stating rather than
leaving as an absence. The GTK backend this SDK carries embeds a
GtkPlug INTO a parent window and never exposes an id of its own;
LV2's X11 UI works the other way round, handing the host a window it
will reparent. Bridging the two is a small change and an untestable
one: WSL has no display, so it would ship having never been opened.
The rest of this SDK does not claim what it has not run, and neither
does this.
Cocoa (ui:CocoaUI): macOS, same argument, and macOS is unverified here
for the separate reason that CI cannot run at all.
SONORE_LV2_UI is the one switch. Where it is undefined the plugin builds exactly as it did before this file existed and its manifest promises no interface, which is better than promising one that will not open.
Types 5
LV2_Feature, transcribed: one capability the host offers, named by URI, with data whose meaning that URI defines. A host hands instantiate() a null-terminated array of pointers to these, valid for that call; anything kept must be copied. The layout is the C ABI's and must not change.
LV2UI_Descriptor, transcribed: what lv2ui_descriptor() returns to the host -- the UI's URI and the four entry points. The layout is the C ABI's and must not change; this module's one instance is static and lives as long as the library.
The host calls idle() on the main thread, which is where a WebView's message loop has to be pumped and where anything the page said gets turned into a port write. Returning non-zero asks the host to close the UI.
LV2UI_Resize, transcribed: the ui:resize feature. A host that offers it is told the interface's size through ui_resize(handle, width, height); a host that does not simply takes the window at the size it is made.
One open LV2 interface, the handle instantiate() returns to the host: the webview, the host's write_function, and what the page and the plugin have said to each other that has not been delivered yet.
Shares nothing with the plugin instance (see the file comment): parameters arrive through port_event and leave through write_function, the state and notes as atoms. Every call on it is the host's UI thread -- instantiate, port_event, idle, cleanup -- and the host deletes it through cleanup(), except while a file dialog is open (see dialogsOpen).
Functions 11
- fn
inline void chooseFileForPage(UiInstance* ui, const BridgeMessage& m)The page asked for a file.lv2ui::chooseFileForPage · lv2_ui.h:254 - fn
inline void pageUp(UiInstance* ui)The page's bridge came up in a real document: everything it missed. On a reload too, which is why the state is asked for again once the held answer has been spent.lv2ui::pageUp · lv2_ui.h:303 - fn
inline void onBridgeMessage(UiInstance* ui, const BridgeMessage& m)lv2ui::onBridgeMessage · lv2_ui.h:329 - fn
inline Lv2UiHandle instantiate(const Lv2UiDescriptor*, const char* /*pluginUri*/, const char* /*bundlePath*/, Lv2UiWriteFunction writeFunction, Lv2UiController controller, Lv2UiWidget* widget, const Lv2Feature* const* features)lv2ui::instantiate · lv2_ui.h:376 - fn
inline void cleanup(Lv2UiHandle handle)lv2ui::cleanup · lv2_ui.h:446 - fn
inline void portEvent(Lv2UiHandle handle, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)The host telling the interface a control moved. Only float control ports; anything else is a protocol the page has no way to render.lv2ui::portEvent · lv2_ui.h:463 - fn
inline int idle(Lv2UiHandle handle)lv2ui::idle · lv2_ui.h:563 - fn
inline int uiResize(void* handle, int width, int height)ui:resize as the interface's own: the host tells it the size its window now is -- a plugin window dragged larger -- and the page follows, within the plugin's editor limits. A plugin whose editor resizes on neither axis refuses. Without it the page stayed the size it opened at inside a host window of any size. The handle field is the host's to ignore here: the interface's own handle is the first argument.lv2ui::uiResize · lv2_ui.h:640 - fn
inline const void* extensionData(const char* uri)lv2ui::extensionData · lv2_ui.h:650 - fn
inline const char* uiUri()lv2ui::uiUri · lv2_ui.h:662 - fn
inline const Lv2UiDescriptor* descriptor(uint32_t index)lv2ui::descriptor · lv2_ui.h:674
Aliases 4
- using
using Lv2UiWidget = void*lv2ui::Lv2UiWidget · lv2_ui.h:76 - using
using Lv2UiHandle = void*lv2ui::Lv2UiHandle · lv2_ui.h:77 - using
using Lv2UiController = void*lv2ui::Lv2UiController · lv2_ui.h:78 - using
using Lv2UiWriteFunction = void (*)(Lv2UiController controller, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)How the interface tells the host a control moved.lv2ui::Lv2UiWriteFunction · lv2_ui.h:82format0 means the buffer is a single float and the port is an ordinary control port.