204 lines
12 KiB
Markdown
204 lines
12 KiB
Markdown
# GUI guidelines
|
|
|
|
Use FLTK/C++ for windows, menus, dialogs, and the event loop. Keep all audio
|
|
engine and project-domain logic in C.
|
|
|
|
Main views:
|
|
- Sequencer: tracks, clips, ruler, playhead, selection, zoom and scrolling.
|
|
- Mixer: channels, faders, pan, mute/solo and meters.
|
|
- Modular graph: nodes, ports, connections, validation feedback.
|
|
- Transport: play/stop/record, tempo, meter, loop and position.
|
|
|
|
Use custom-drawn widgets where ordinary controls are not a good fit: timeline,
|
|
waveforms, piano roll, mixer strips and graph canvas. Keep drawing separate
|
|
from project mutation. Never call FLTK from the audio thread.
|
|
|
|
Visual direction: compact, high-contrast, restrained dark interface. Avoid
|
|
excessive animation and modal configuration. Recreate broad usability ideas,
|
|
not energyXT's exact artwork or proprietary resources.
|
|
|
|
## Phase 3 shell
|
|
|
|
The shell opens JACK on startup through `xtc_backend.h`. It never accesses
|
|
backend structures, processes samples, or calls JACK itself. Graph domain
|
|
data is owned by opaque C objects, manipulated only through the C API. All backend control calls run on the GUI thread; FLTK is never called
|
|
from an audio callback. No server is started and no audio ports are connected
|
|
by the GUI. The initially empty graph produces silence.
|
|
|
|
- **Play / F5:** start the engine. **Stop / F8:** deactivate it. **Pause / F7:** hold playback. **Space:** toggle Play/Stop.
|
|
**To start / Home:** stop and seek to zero. Pause/Home are disabled while recording.
|
|
These advance/pause the sample-counted playhead; imported audio clips play through their graph source.
|
|
- **Reconnect / F6:** close the old client and open a fresh stopped client.
|
|
Use this after server loss or sample-rate changes. A failed close preserves
|
|
the handle and reports the failure instead of opening another client.
|
|
- **View menu / Ctrl+1, Ctrl+2, Ctrl+3:** switch between sequencer, mixer and
|
|
modular graph. Tabs provide the same view switching. Mixer, graph and sequencer editors are described below.
|
|
- **File / Quit / Ctrl+Q** or the window close button: close the backend and
|
|
synchronize audio callbacks before hiding/destroying widgets. A failed close
|
|
leaves the window open for a retry. New/Open/Save actions are described below. About identifies the development milestone and version.
|
|
|
|
The indicator shows disconnected, ready, running, server lost, format changed
|
|
or process-error states. The status line shows rate, actual block size, mono
|
|
layout, processed block count, xruns and process result. Command errors remain
|
|
visible until a successful control action; periodic refresh does not erase them.
|
|
A GUI-owned 100 ms timer reads atomic snapshots and collects retired plans.
|
|
Label text changes only when needed. The timer is removed before successful
|
|
close and again by the window destructor. No GUI locks are held across control
|
|
calls. Operations such as opening JACK can briefly block the GUI; there is no
|
|
worker/control-thread framework in this initial shell.
|
|
|
|
MainWindow owns the backend handle and FLTK owns the window's children. The
|
|
destructor also attempts cleanup on exceptional event-loop exit; if JACK close
|
|
itself fails then, it reports to stderr and retains the callback context until
|
|
process exit. Normal close/reconnect paths permit retry and release ownership
|
|
only after successful close. The entry point catches C++ exceptions before
|
|
process exit. Backend operations return C error codes throughout.
|
|
|
|
Tests: `make test-gui` runs real widgets/callbacks/timers against a fake C backend
|
|
under Xvfb, including control errors, startup without JACK, partially initialized
|
|
handles, server/format notifications, view switching, retrying close, and timer
|
|
removal. `make test-gui-jack` additionally requires a running JACK-compatible
|
|
server, tests repeated start/stop, reconnect and active-client close, and creates
|
|
no routes. Physical playback is outside this shell. See BUILD.md and the
|
|
integration test README for sanitizer limitations and keyboard smoke results.
|
|
|
|
## Phase 4 modular editor
|
|
|
|
Open **Modular Graph** or press **Ctrl+3**. Add oscillator (440 Hz), gain (0.10),
|
|
pass-through meter or output nodes with the toolbar. Their parameters are fixed
|
|
presets in this milestone and are drawn on each node; parameter editing and
|
|
live meter display are not implemented. Connect oscillator → gain → meter →
|
|
output for a simple test chain. No sound reaches hardware until ports are
|
|
explicitly connected outside the GUI. Output nodes are required to render;
|
|
isolated sources and an empty graph produce silence.
|
|
|
|
Drag a node body/title to move it. Drag a circular output port to an input port
|
|
to connect. Click a node or wire to select it (yellow outline/wire), then press
|
|
Delete/Backspace or **Delete selection**. Deleting a node deletes its incident
|
|
wires. Escape cancels a drag preview. Canvas scrollbars pan the view; positions
|
|
are retained across edits/reconnect but not across application restart. There
|
|
is no graph zoom, multiselection, undo or external routing UI yet.
|
|
The editor supports 64 nodes on a fixed 2000x4000 canvas.
|
|
|
|
Every semantic action becomes a C graph command. The window owns a C project containing the graph
|
|
handle and publishes the C-created candidate through the backend. Cycle,
|
|
invalid-direction, duplicate connection, missing-port, capacity and backend
|
|
failures are shown below the canvas; failed edits leave the graph unchanged.
|
|
Capacity feedback distinguishes the possible node limit/pending edit condition
|
|
and allows retry. Editing while stopped replaces the prepared plan without
|
|
starting playback. Editing with a disconnected startup backend stays local
|
|
until reconnect. A lost or changed live backend requires reconnect before
|
|
further semantic edits. Moving/selecting nodes does not touch the engine.
|
|
|
|
The graph state line distinguishes offline, prepared, queued and active states.
|
|
Queued explicitly means the drawing represents the next submitted graph while
|
|
the engine finishes the previous plan. The 100 ms GUI timer observes audio
|
|
adoption revisions and then shows active. Graphs are not edited in place on the
|
|
audio thread. There is no automatic retry/hidden edit queue; users retry a
|
|
rejected capacity edit. Plan replacement can reset oscillator phase and is not
|
|
crossfaded. Render validation and active replacement tests are described in
|
|
tests/integration/README.md.
|
|
|
|
|
|
## Phase 5 projects and sequencer
|
|
|
|
File/New (Ctrl+N), Open (Ctrl+O), Save (Ctrl+S), and Save As
|
|
(Ctrl+Shift+S) use native file dialogs and the C persistence API. New/Open/Quit
|
|
offer Cancel/Discard when semantic edits are unsaved; save first to retain them.
|
|
Save As confirms overwrites. The title marks unsaved changes. Failed loads and
|
|
backend submissions retain the old document. Loading parses before stopping
|
|
audio; installing a valid candidate stops and resets transport before compiling
|
|
and submitting. A later failure can leave the retained document stopped at zero.
|
|
Opening/New resets graph layout; graph positions are not saved. See PROJECT_FORMAT.md.
|
|
|
|
Sequencer offers Add track, Add region, Delete region/track, Zoom +/-. Select a
|
|
track header to add a one-bar region there at the cursor. Select a region to
|
|
delete it; deleting a selected track cascades to its regions. Delete also works
|
|
with canvas focus. Drag a region body to move it in time or between tracks;
|
|
drag either edge to trim within its original source bounds. Edits commit on
|
|
release with 1/16-note snapping; Escape cancels. There is no drag preview, undo,
|
|
multiselection, rename or tempo editor yet. Overlapping regions are permitted.
|
|
|
|
The scrollable canvas expands to cover the arrangement plus a margin; zoom
|
|
ranges from 24 to 384 pixels/quarter. Names, tempo and 4/4 meter are drawn.
|
|
A ruler click seeks while stopped (or positions the cursor when disconnected).
|
|
The 100 ms GUI refresh converts the backend's actual sample counter to ticks;
|
|
it never integrates wall-clock time. Play resumes and Stop pauses. Reconnect,
|
|
New and Open reset position. Add region creates silent metadata; imported WAV clips play through the
|
|
audio source node (Phase 6 below). MIDI clips and notes are described below. The C model
|
|
supports a constant tempo; a tempo map and scheduler are future work.
|
|
|
|
Tests cover C-model/persistence boundaries, GUI move/trim gestures and zoom,
|
|
save/reopen, failed load/submission rollback, sample-derived cursor updates,
|
|
and live JACK playhead advance/pause.
|
|
|
|
|
|
## Phase 6 audio workflow
|
|
|
|
Use File/Import WAV (Ctrl+I) to add an audio clip at the playhead on the selected
|
|
track, or on a new Audio track. Record (Shift+F5) chooses a WAV destination and
|
|
captures JACK input until Stop finalizes and adds the take. No input routes are
|
|
created automatically. Save after Stop; the project references the external WAV.
|
|
|
|
Import creates an Audio clips graph source and output route if the source is
|
|
absent. Modular Graph offers Add audio source for explicit routing through gain
|
|
or meter nodes. All tracks currently share one mono timeline mix. Arrangement
|
|
edits stop playback; graph edits remain live outside recording. During recording,
|
|
edits, file actions, reconnect and close require Stop first.
|
|
|
|
Open/Play reports missing, unreadable or unsupported assets, preserving their
|
|
regions as silence. The backend status shows the unique issue count. Select a
|
|
clip and use File/Relink selected audio to choose another path; Play validates
|
|
the replacement. Playback uses preloaded immutable samples; imports and loads
|
|
can block the GUI while reading, but never the audio callback.
|
|
|
|
See AUDIO_FILES.md for supported WAV formats, memory limits, musical placement,
|
|
recording overflow/partial-take recovery, external asset portability and the
|
|
software-only acceptance tests. Waveform drawing, input monitoring, recording
|
|
latency compensation and per-track graph inserts are not implemented.
|
|
Per-track gain/pan/mute/solo is available in Phase 8 below.
|
|
|
|
## Phase 7 piano roll
|
|
|
|
Add MIDI clip creates a one-bar clip on the selected/first existing track at the
|
|
cursor. Select it and choose Piano roll (View/Piano roll, Ctrl+4). Click to draw,
|
|
drag a body to move pitch/time, drag its right edge to resize, and right-click
|
|
or Delete to remove. Notes use source ticks with 1/16 snapping; trimmed source
|
|
content is retained. Edits stop transport and are blocked during audio recording.
|
|
Panic/F9 silences held notes; Record continues to mean WAV audio capture.
|
|
Modular Graph offers Add instrument for explicit routing. Status includes MIDI
|
|
drops. See MIDI.md for voice limits, unsupported messages and live input routing.
|
|
|
|
## Phase 8 mixer and editing
|
|
|
|
Mixer (Ctrl+2) now has a selectable track strip, gain/pan controls, mute/solo,
|
|
Output L/R peaks and editable gain/pan automation lanes. Mixer edits stop
|
|
playback. Click the lane to add/replace points, right-click near a point to
|
|
remove, and change First tick to navigate. Ctrl+Z, Ctrl+Shift+Z and Ctrl+Y undo
|
|
and redo up to 32 project edits; New/Open resets history. M/S and arrow keys
|
|
provide mixer shortcuts. See MIXER.md for exact controls, history rollback,
|
|
stereo port routing, automation semantics and prototype limits.
|
|
|
|
## Phase 11 minimal composition workflow
|
|
|
|
[WORKFLOW.md](WORKFLOW.md) walks through creating, arranging, saving, closing,
|
|
reopening and playing MIDI/audio with the GUI. New/Open select Sequencer;
|
|
Ctrl+3 still opens the modular graph. Stop retains its established position-hold
|
|
behavior and finalizes recording; explicit Pause retains position without
|
|
finalizing a take (and is refused during recording). Home stops and returns to
|
|
zero. Failed candidate installation now refreshes the actual backend state
|
|
even when the previous document is retained.
|
|
|
|
`make test-workflow` uses a live JACK-compatible backend and Xvfb, with exact
|
|
stereo render comparisons across destruction/recreation of the GUI and live
|
|
playhead/meter/transport checks. `test-gui` covers stop/seek failure and recording
|
|
guards. No project files need manual editing for this workflow.
|
|
|
|
## Phase 12 timing and transitions
|
|
|
|
The GUI enables 5 ms source boundaries and master start/stop ramps. Ordinary
|
|
Pause/Stop now request a fade and show “stopping” until the timer collects its
|
|
acknowledgement and deactivates JACK. Recording Stop, Home, fault handling and
|
|
project installation retain immediate semantics. See
|
|
[AUDIO_QUALITY.md](AUDIO_QUALITY.md) for timing, overload/denormal behavior, latency
|
|
limits, test commands and the pending human-listening checklist.
|