Wine-NSPA – Lulada

Lulada is a Linux Digital Audio Workstation built on a winelib runtime. It combines DAW sequencing, recording, automation, JACK-native audio/MIDI, and in-process Windows VST2, VST3, and CLAP plugins in one Linux application.

Table of Contents

  1. Overview
  2. DAW surfaces
  3. System architecture
  4. Session View and Arrangement
  5. MIDI authoring
  6. Sampler and automation
  7. JACK audio and MIDI engine
  8. Windows plugin runtime
  9. Window embedding and UI policy
  10. Runtime boundary
  11. References

1. Overview

Lulada is the Wine-NSPA DAW application. Its core application model is a modular music-production environment: clip launching, linear arrangement, multi-track recording, tracker sequencing, piano-roll editing, sample playback, automation, JACK routing, and plugin processing are all part of the same session graph.

The Windows-plugin path is an implementation capability inside that DAW. VST2, VST3, and CLAP plugins are loaded in-process through JUCE-NSPA and Wine-NSPA, so plugin DSP, plugin editors, JACK graph routing, and the DAW transport all share one Linux process.

Lulada Digital Audio Workstation Composition surfaces Session View clip grid + scenes Arrangement / Timeline lanes tracker and piano-roll MIDI editors multi-track recording and region editing DAW engine modular graph and nested subgraphs sampler, automation, MIDI tools disk-streamed playback and recording sample-accurate launch and MIDI timing Windows plugin runtime VST2, VST3, and CLAP PE modules loaded in-process through Wine-NSPA Win32 editor HWNDs embedded in UI async plugin instantiation path JACK-native transport audio callback is the period boundary combined and per-port JACK MIDI buffers direct same-period output writes Native Linux shell GL-backed application window Wayland peer support, X11 fallback internal file choosers and graph UI one DAW session graph owns composition, routing, plugins, automation, recording, and playback

2. DAW surfaces

Surface Current implementation
Session View clip grid, scenes, per-column track strips, scene launch, scene tempo/time-signature override, follow actions, stop buttons, and sample-accurate audio-thread launch scheduling
Arrangement / Timeline audio and MIDI lanes, region move/resize/split/snap, looped regions, clip gain, Bezier fade curves, marker track, ruler interaction, and disk-streamed audio record/playback
Multi-track recording track-oriented audio recording through disk-streaming services, with graph auto-wiring for the multi-track patchbay
Tracker vendored VHT-style tracker engine, pattern grid, QWERTY note entry, per-cell FX columns, multi-pattern sequencing, per-row delay/probability/range, row-per-beat control, mute/solo, and MIDI recording
Piano-roll MIDI note regions, viewport/zoom/tools, velocity lane, snap divisions, ruler, playhead, Alt-copy, axis lock, edge resize, clipboard, quantize, humanize, and scale-snap with live preview
MIDI clips first-class sources shared by Session View and Arrangement, backed by copy-on-write MIDI note region data
Sampler FT2-style mixer DSP, multi-instrument bank/slot workflow, volume/pan envelopes, voice-level FX, pitch/mod-wheel routing, four stereo bus outputs, AVX2 mix path, and session-global sample pool
Automation copy-on-write automation point/region/track model, curve math, sample-accurate MIDI CC dispatch, touch-record FIFO, mute table, and session XML round-trip
Modular graph audio, MIDI, JACK ports, sequencers, samplers, internal processors, and Windows plugins are routable nodes in the same graph
Plugin processing in-process Windows VST2, VST3, and CLAP nodes run beside native DAW processors

3. System architecture

Lulada separates DAW ownership from runtime substrate ownership. The DAW owns the session model, graph topology, timeline, clip launching, MIDI editors, sampler, automation, JACK policy, plugin scan policy, and UI presentation. JUCE-NSPA and Wine-NSPA provide the Windows-plugin and native-peer substrate used by that application.

Layer Responsibility
Lulada application shell main window, view switching, session/document commands, graph UI, plugin manager, internal dialogs, and visual identity
Composition model Session View cells/scenes plus Arrangement/Timeline lanes and regions
Authoring engines tracker, piano-roll, sampler, automation, MIDI source/region services
Graph engine audio/MIDI routing, internal processors, Windows plugin nodes, nested subgraphs, multi-track patchbay wiring
JACK engine audio period boundary, native audio ports, native MIDI ports, same-period MIDI ingress/egress
JUCE-NSPA winelib build support, Windows VST2/VST3/CLAP plugin formats, WineHWNDEmbedComponent, Wayland peer support, async plugin-load helper path
Wine-NSPA Win32 loader/runtime, wineserver, Wine thread state, X11/Wayland embed protocol, Win32 priority mapping

The important boundary is that plugin execution is one subsystem inside the DAW. It does not define the whole application model.


4. Session View and Arrangement

Lulada has both live clip-launching and a linear arrangement model. Session View is organized around cells, scenes, per-column track strips, follow actions, scene-level tempo/time-signature overrides, and sample-accurate launch scheduling on the audio thread. Arrangement/Timeline provides audio and MIDI lanes with region authoring, marker navigation, loop ranges, clip gain, fade curves, and disk-streamed audio playback/recording.

The two surfaces share clip data instead of acting as unrelated modes. MIDI clips are first-class sources that can appear in Session View and Arrangement, and the timeline services keep source/region/lane ownership explicit.

Shared clip model: live launching and linear arrangement Session View clip cells, scenes, follow actions per-scene tempo / time signature audio-thread launch scheduler Shared sources and regions MIDI note regions and audio regions copy-on-write source data lane / playlist ownership Arrangement / Timeline audio + MIDI lanes move / resize / split / snap loop, gain, fades, markers Graph execution clip, timeline, MIDI, sampler, automation, and plugin nodes render through the same graph

5. MIDI authoring

Lulada has two main MIDI composition surfaces.

Surface Role
Tracker pattern-first MIDI sequencing with QWERTY entry, per-cell FX columns, block editing, multi-pattern sequences, row-level timing/probability/range controls, track loop controls, and mute/solo
Piano-roll note-region editing with velocity lane, snap divisions, ruler/playhead, drag/trim/copy gestures, clipboard, quantize, humanize, scale-snap, and live preview

Both editors feed the same MIDI source/region infrastructure. That matters for the DAW model: tracker phrases, piano-roll clips, Session View cells, and Arrangement MIDI regions are not separate plugin-host side channels. They are composition data inside the project.


6. Sampler and automation

The sampler is an internal DAW instrument, not an external dependency. It uses an FT2-style mixer core with multi-instrument bank/slot workflow, volume and pan envelopes, voice-level FX, pitch/mod-wheel routing, four stereo bus outputs, and an AVX2 SIMD mix kernel. The session-global sample pool exposes 128 banks with 32 slots per bank, and sample-bank state round-trips through the session.

Automation is also internal to the engine. The current implementation uses a copy-on-write automation model with point, region, and track objects, curve math, target dispatch, sample-accurate MIDI CC output, a touch-record FIFO, and session XML round-trip.


7. JACK audio and MIDI engine

The Linux build is JACK-first. JACK is the audio transport, MIDI transport, and the timing boundary for realtime graph execution. ALSA-seq is disabled in this build.

Current inbound MIDI path:

  1. JackAudioIODevice::process() reads each enabled midi_in_N port with jack_midi_event_get().
  2. Events are written into currentPeriodMidiInput for graph-wide MIDI input and currentPeriodMidiInputPerPort[N] for explicit per-port nodes.
  3. The original JACK sample offset is preserved.
  4. AudioEngine, MidiEngine, and JackMidiInputNode consume those buffers during the same period.

Current outbound MIDI path:

  1. the JACK callback clears and caches enabled midi_out_N buffers before the graph renders
  2. JackMidiOutputNode and JackMidiOutputAllNode write directly through writeJackMidiOutput()
  3. jack_midi_event_write() receives the caller’s sample offset for the current period
  4. cached output buffers are invalidated before the callback returns

The graph exposes JACK MIDI as topology: combined input, per-port input nodes, per-port output nodes, and broadcast output nodes are explicit graph surfaces.


8. Windows plugin runtime

Windows plugin support is integrated into the DAW process through JUCE-NSPA and Wine-NSPA.

Surface Current behavior
VST2 enabled through the system Steinberg VST2 SDK 2.4
VST3 enabled for Windows VST3 modules loaded through the winelib runtime
CLAP enabled under __WINE__ through JUCE-NSPA CLAPPluginFormat for Windows .clap PE DLLs
LV2 / LADSPA / AU not registered in the winelib configuration
Built-in nodes sampler, tracker, MIDI tools, audio FX, and internal processors remain native Lulada nodes

The scan surface is limited to 64-bit Windows-plugin directories inside the active WINEPREFIX:

Program Files (x86) is intentionally excluded because the host is x86_64 winelib and cannot load 32-bit plugin DLLs.

Interactive plugin add uses an asynchronous creation path. Lulada requests node creation, JUCE-NSPA performs plugin instantiation on a winelib CreateThread worker, then completion returns to the message thread for node attachment and UI update. Large plugin descriptors and port lists therefore do not block the DAW shell while they are materialized.


9. Window embedding and UI policy

Lulada uses JUCE-NSPA’s embedded Win32 editor layer for plugin UI surfaces. Plugin editors are Wine HWND-backed windows embedded under the DAW’s native Linux window tree.

Surface Owner Current behavior
Main DAW shell Lulada GL-backed native application window, Session View, Arrangement, graph, mixer/channel surfaces, plugin manager, and internal dialogs
X11 plugin embed JUCE-NSPA + Wine-NSPA WineHWNDEmbedComponent creates the Win32 editor HWND and Wine-NSPA embeds the native X11 child under the host peer
Wayland plugin embed JUCE-NSPA + Wine-NSPA JUCE-NSPA owns the host wl_display; Wine creates a child wl_surface and installs it as a subsurface of the JUCE peer
Message pump JUCE-NSPA whole-thread queue pumping, input-first passes, and bounded general drain
Dialog policy Lulada Open Session, Save As, Import Graph, and Export Graph use JUCE internal choosers parented on the main content component

The UI layer also uses a type-color system so graph blocks, wires, and channel strips identify Audio I/O, JACK MIDI, VST2, VST3, CLAP, and internal nodes without relying on plugin names.


10. Runtime boundary

Boundary Current behavior
Application type Linux x86_64 Digital Audio Workstation
Runtime model winelib application using Wine-NSPA for Win32 plugin execution
Window system Wayland when available, X11 fallback
Audio/MIDI backend JACK
Windows plugin formats VST2, VST3, CLAP
Linux-native external plugin formats excluded in the winelib configuration
Built-in processors native Lulada graph nodes
Project model session graph with clip, arrangement, tracker, piano-roll, sampler, automation, plugin, and routing state

Startup prepares Wine state before plugin code executes: the host ensures a wineserver socket exists, promotes the process with SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS), and calls OleInitialize(nullptr) before plugin initialization reaches static constructor-heavy code paths.


11. References