feat(midi): qualify routed startup and refresh workflow screenshots (phase 105)

This commit is contained in:
Johannes Findeisen 2026-11-06 02:35:48 +01:00
commit 25d4ad5d3b
73 changed files with 208 additions and 37 deletions

View file

@ -82,3 +82,8 @@ Unterminated notes, zero source duration and malformed events reject rather than
silently dropping notes. Unmatched note-offs are harmless and ignored. Overlapping
same-pitch notes pair FIFO within each file track/channel. Project save/reload
uses the existing format; no format migration or extra dependency is required.
Configured startup holds the transport clock and emits silence until selected
MIDI ports are connected, so notes at the song start are not consumed before
routing. MIDI routing retries publication for at most 100 ms on the control
thread; the callback never sleeps or calls the JACK graph connection APIs.

View file

@ -3,11 +3,12 @@
Open **Edit / Preferences** (Ctrl+,). Each tab edits application settings.
**Apply** validates every tab, saves `~/.xtc.conf`, and applies the values.
**Close** discards edits made since the last Apply. Apply stops playback; stop
recording before opening Preferences. Missing configuration uses defaults.
recording before opening Preferences. Clean exit also saves collected application settings.
Startup reads `~/.xtc.conf` before project/backend creation; missing keys use defaults.
Malformed configuration reports an error and uses defaults without overwriting
it. Invalid input or failed writes preserve the previous saved configuration.
The file is INI with `[audio]`, `[plugins]`, `[interface]`, `[editing]`,
The file is INI with `[audio]`, `[plugins]`, `[midi]`, `[interface]`, `[editing]`,
`[project_defaults]` and `[transport]` sections. Save uses a mode-0600 temporary
file, flushes and fsyncs it, then atomically renames it. Unknown keys/sections,
duplicate keys, invalid ranges, embedded NULs and files larger than 64 KiB are
@ -18,7 +19,8 @@ may be quoted, with `\\` and `\"` escapes. Apply rewrites comments and formattin
| --- | --- |
| audio | `client_name="xtc"`, `max_frames=65536`, `channels=2`, `transition_ms=5`, `offline_rate=48000`, `recording_seconds=2` |
| plugins | `clap_paths`, `vst2_paths`, `vst3_paths`, `ladspa_paths`: colon-separated `~/.clap`, `~/.vst`, `~/.vst3`, `~/.ladspa`, followed by corresponding `/usr/local/lib/` and `/usr/lib/` directories |
| interface | `width=1280`, `height=800`, `piano_width=900`, `piano_height=620`, `refresh_ms=100` |
| midi | `midi_input_port=""`, `midi_output_port=""`, `midi_input_channel=-1`, `midi_output_channel=-1`, `midi_thru=0`; ports connect on Play/Record |
| interface | `main_x=0`, `main_y=0`, `inspector_visible=0`, `width=1280`, `height=800`, `piano_width=900`, `piano_height=620`, `refresh_ms=100` |
| editing | `sequencer_snap=240`, `piano_snap=240`, `sequencer_zoom=48`, `clip_ticks=3840`, `note_ticks=960`, `note_velocity=100`, `note_channel=0`, `filter_channel=-1`, `filter_low=0`, `filter_high=127` |
| project_defaults | `tempo=120000` (milli-BPM), `volume_cc=7`, `pan_cc=10`, `sustain_cc=64` (128 disables a mapping) |
| transport | `loop_start=0`, `loop_end=3840`, `loop_enabled=0`, `follow_playhead=0` |
@ -34,7 +36,7 @@ safety limits and plugin ABI requirements are not runtime preferences.
Snap accepts 1 (Off), 120, 160, 240, 320, 480, 960, 1920 or 3840 ticks.
Zoom accepts 24, 48, 96, 192 or 384 pixels per beat. MIDI channels are zero-based;
filter channel -1 shows all channels. Window sizes, grids and filters currently
in use populate Preferences when it opens; press Apply to persist them.
in use populate Preferences when it opens; Apply or a clean application exit persists them.
Plugin selection now opens a library of `.clap` and `.so` files from the search
paths. `~/` expands to the home directory; empty/nonabsolute roots are skipped.
@ -49,7 +51,7 @@ other locations. It is not a plugin certification or isolation service.
**Shift-drag the sequencer ruler** to select a region using the selected Snap.
Dragging in either direction works. A band shows the region; **Loop** enables
or disables it. **Loop range...** also accepts start and end in ticks. Selection
and toggling take effect immediately; Apply in Preferences persists the region.
and toggling take effect immediately; Apply or clean exit persists the region.
The region is global application configuration and is not stored in `.xtc`
projects. Changing a region during playback stops, reconfigures and restarts the
backend. Selecting a region does not itself enable looping.
@ -73,12 +75,19 @@ playback stopping uses the GUI timer and is disabled during looping/recording.
See BUILTIN_DEVICES.md for endpoint, cancellation and reset semantics.
Phase 45 adds `[interface] transport_detached`, `mixer_detached`, and each
panel's `_x`, `_y`, `_width`, `_height` rectangle. Use Preferences / Apply after
panel's `_x`, `_y`, `_width`, `_height` rectangle. Use Preferences / Apply or close the application cleanly after
moving panels to save the captured layout. Restoration clamps rectangles to the
current display; the floating transport wraps at narrow widths.
Phase 46 extends `[interface]` with `sequencer_detached`, `graph_detached`,
`piano_detached`, editor window geometry and `track_header_width` (180..360).
Piano retains `piano_width`/`piano_height` and adds `piano_x`/`piano_y`.
Reset workspace layout changes the session; Preferences / Apply persists it.
Reset workspace layout changes the session; Preferences / Apply or clean exit persists it.
Only original-tab docking and floating windows are supported.
Phases 100–105 extend configuration with complete workspace collection and MIDI
ports/channels/thru. Invalid startup files are preserved on exit; explicit Apply
can replace them after validation. If saving fails, the window stays open for
retry. See [MIDI_WORKFLOWS.md](MIDI_WORKFLOWS.md) for device setup and notes-only
Standard MIDI File import/export. JACK server hardware settings and musical
project contents remain owned by the server and project respectively.

View file

@ -1006,7 +1006,8 @@ Persist application preferences in `~/.xtc.conf` and provide selectable sequence
### Implementation status
Implemented without dependencies or a project format change. Application settings
are saved only with Apply; audio connection options take effect on Reconnect and
were initially saved only with Apply; Phase 100 also saves on clean exit.
Audio connection options take effect on Reconnect and
project defaults on New. Existing projects retain their musical data. Loop ranges
are global preferences, not project data. Enabled loops require at least 64 samples.
See [PREFERENCES.md](PREFERENCES.md) for configuration, workflow and limitations.
@ -2301,15 +2302,38 @@ Implemented: bounded C99 type 0/1 PPQN notes import with running status, channel
Capture current MIDI preferences, file workflows and imported notes, refresh the gallery, and qualify configuration, MIDI I/O and file workflows together.
### Tasks and acceptance criteria
- [ ] Implement and document the workflow with bounded validation and safe ownership.
- [ ] Pass meaningful core and GUI checks, including errors and persistence or undo.
- [ ] Commit this phase separately after validation.
- [x] Implement and document the workflow with bounded validation and safe ownership.
- [x] Pass meaningful core and GUI checks, including errors and persistence or undo.
- [x] Commit this phase separately after validation.
### Implementation status
Planned.
Implemented: all 66 gallery PNGs were refreshed, including five new MIDI preferences/help/file-menu/import captures through real C/GUI workflows. A real-process isolated-home test proves ~/.xtc.conf creation, startup reload and malformed-file preservation. Final routing qualification adds bounded PipeWire publication retry and holds transport until chosen routes exist, preserving notes at position zero; deterministic callback and real receiver checks pass. Full core/reliability, GUI/plugin/JACK, optional-backend builds, ASan/UBSan, static analysis and staged installation checks passed.
---
## Integrated Validation for Phases 100–105
Completed on 2026-11-06. Normal builds use `BUILD_DIR=build/audio-editor`:
`all gui test-reliability`, `test-gui-midi-workflows`, `test-gui-creative`,
`test-gui-track-fx`, full `test-gui`, modern-plugin/instrument/LADSPA GUI fixtures,
`test-gui-jack`, `test-jack-midi`, and `test-configuration-startup` passed.
The final routed-start change was rechecked with core/reliability, full/focused
GUI, live MIDI first-note receipt and real-process configuration startup tests.
`BUILD_DIR=build/midi-minimal PKG_CONFIG=false FLTK_CONFIG=false all test` passed.
Clang ASan/UBSan full core/reliability and focused/full GUI checks passed using
only the existing Fontconfig leak suppression. The existing Clang/FLTK redundant
instrumentation warning remains; normal warning-enabled builds are clean.
Clang static analysis (including a final backend recheck), default/custom staged
install layouts and C/C++ pkg-config consumers passed.
The full gallery and host VST3/creative/MIDI capture modes regenerated 66 PNGs.
File import is notes-only type 0/1 PPQN and retains project tempo. MIDI devices
are JACK/PipeWire ports; physical hardware/bridge compatibility is not claimed
from software-port tests. No dependencies or project-format change were added.
See [MIDI_WORKFLOWS.md](MIDI_WORKFLOWS.md), [PREFERENCES.md](PREFERENCES.md) and
[the gallery](../screenshots/README.md) for reproduction and exact limits.
## Recommended Execution Order
Reorder the phases when the audit reveals a blocking dependency. Do not mark a phase complete merely because code exists: its acceptance criteria must be demonstrated by builds, tests, or documented manual verification.

View file

@ -114,7 +114,8 @@ Duplicate, Rename and Delete. Invalid/capacity edits retain the existing model.
View/Snap selects 1, 120, 240 (default), 480 or 960 ticks. It affects ruler seeks,
clip moves and trims; 1 tick is the finest grid. Existing +/- zoom and scrollbars
retain their behavior. Piano roll has its own configurable grid (see MIDI.md); mixer lanes retain their 240-tick
grid. Grid/zoom/selection are session UI preferences, not undoable music edits.
grid. Grid and zoom are application preferences saved on Apply/clean exit;
selection is session state. These controls are not undoable music edits.
Escape cancels a drag; Delete affects the focused editor; text fields keep their
own editing keys. Commands are named in menus/tooltips and timeline focus accepts
keyboard editing; screen-reader and broad accessibility qualification are pending.

View file

@ -164,7 +164,7 @@ and meters; the main Mixer tab offers Show and Dock actions while it is floating
The transport owns the playback buttons, position, **BPM**, **Loop** toggle and
**Loop range...** settings in both layouts. Shift-drag on the sequencer ruler
still updates the same loop region. BPM remains an undoable project edit;
loop preferences retain their existing Preferences / Apply persistence behavior.
loop preferences persist through Preferences / Apply or clean application exit.
Space and menu playback shortcuts work from either floating panel, with normal
numeric/text editing protection. Closing the main window closes all panels only
after the existing unsaved/recording/backend shutdown checks succeed.
@ -182,8 +182,8 @@ playback shortcuts, failed shutdown and cleanup.
## Phase 45 saved panel layouts
Preferences / Apply now saves transport/mixer dock state and window rectangles.
Open Preferences after arranging the windows to capture their current positions.
Closing the application alone does not save preferences. Startup restores the
Preferences / Apply captures their current positions; Phase 100 also saves on
clean application exit. Startup restores the
saved layout; off-screen rectangles are clamped to an available display's work
area. Invalid dimensions are rejected transactionally by the settings reader.