1
0
Fork 0
forked from hanez/xtc

Phase 13: protect recordings and recover retained audio after write failures

This commit is contained in:
Johannes Findeisen 2026-10-27 03:46:09 +01:00
commit 01d9db90fd
15 changed files with 308 additions and 30 deletions

View file

@ -80,7 +80,7 @@ error rather than hiding gaps or compressing time.
Stop first synchronizes the callback, detaches the recorder, drains remaining
samples, writes the final WAV header, flushes/fsyncs/closes and renames the
same-directory temporary over the destination. A successful nonempty take is
same-directory temporary using an atomic no-clobber link; an existing destination is refused. A successful nonempty take is
imported at its capture position on the selected track (or a new Recording
track), then the document becomes unsaved. Save the project after Stop. Seeking
back to the take and pressing Play auditions it. Recording continues existing
@ -92,7 +92,7 @@ until Stop finishes the take. Deactivation failure retains the recorder for a
safe retry. On overflow a finalized partial WAV is retained for manual recovery
and is not automatically added. On import/preparation failure the completed
take remains at its chosen path with an explicit recovery message. I/O errors
are reported; an unfinished temporary is removed on destruction. Recordings
are reported; failed temporary data is retained and its recovery path is reported. Recordings
are RIFF-limited to 1073741814 frames, but the smaller playback/import asset
limit still applies: longer takes may need external splitting before import.
There is no crash-recovery journal. The file is mode 0600; parent-directory
@ -109,3 +109,31 @@ make test-jack-audio routes only two software clients: known source -> recorded
WAV -> saved/reopened project -> graph playback -> capture assertion.
Physical input/output, device latency, slow-disk endurance and server loss
during a real recording remain unverified.
## Phase 13 recording protection
The default recorder and GUI require a new destination, including rejecting
symlinks. Publication also refuses files created during recording. The explicit
`xtc_recorder_create_replace` API retains authorized replacement for callers
that deliberately need it; the GUI never uses it. After a failed finish, copy
`xtc_recorder_recovery_path` before destruction. Disk-write/finalization failures
retain the temporary. Destruction after producer quiescence attempts to drain
and finalize accepted data; normal code should call finish and inspect errors.
The GUI refuses closure while recording and prints the retained/finalized path
on exceptional destruction.
Use `xtc-check --recover-recording TEMP NEW.wav` to copy complete float32 frames
from an interrupted xtc WAV into a new WAV. Source and existing destinations are
never modified. A trailing partial frame is ignored. This handles xtc's canonical
44-byte mono float32 header only, not arbitrary damaged WAVs. Recovery is explicit
and control-thread only; no orphan scan runs during playback.
`make test-recording` simulates 30 minutes at 8 kHz with repeated ring wrapping
and draining, destination races/symlinks, a child-local disk-size limit, prefix
recovery and incomplete/missing asset reopening. `test-recovery` retains process
kill coverage; `test_audio` covers saturation and concurrent drain. This is
virtual-duration testing, not a wall-clock hardware endurance qualification.
Recordings remain RIFF mono float32, bounded to roughly 4 GiB; the preloaded
player still limits each asset to 16M frames. Longer valid takes may require
external splitting before import. No directory fsync/power-loss guarantee is
claimed. WAV destinations are chosen explicitly by the user.

View file

@ -46,3 +46,14 @@ eight project writers while temporaries are visible, and kills a recorder after
draining but before finalization. Complete old/new destinations and explicit
orphan temporaries are verified. It does not cut power, terminate the shared
audio server, simulate a failing filesystem, or qualify disk/device endurance.
## Phase 13 retained recording prefixes
Recording now defaults to no-clobber publication; the GUI requires an unused
path. Failed nonempty temporary recordings survive destruction. Query the
recorder recovery path before destruction, or use the GUI's reported path.
`xtc-check --recover-recording TEMP NEW.wav` reconstructs a canonical mono
float32 WAV from complete on-disk frames, ignoring a trailing partial frame.
It never changes the source or overwrites an existing destination. This
supersedes the earlier lack of a WAV recovery tool described above. See
AUDIO_FILES.md for format/ownership/size limits and `make test-recording`.

View file

@ -233,6 +233,15 @@ limiter or project-format change is claimed.
- Incomplete recordings and missing media are detected and explained.
- Recording and recovery behavior is covered by automated or repeatable integration tests.
Implemented: no-clobber recording destinations and race-safe publication;
explicit opt-in replacement API; retained failed temporaries and recovery-path
reporting; streaming `xtc-check --recover-recording TEMP NEW.wav` salvage;
quiescent destructor draining and exceptional-shutdown reporting. Virtual
30-minute recording, saturation/concurrency, destination races, disk-write
failure/prefix recovery, killed writers and missing/incomplete media tests pass.
See AUDIO_FILES.md and RECOVERY.md. Physical endurance, power-loss guarantees
and playback of assets above the existing preload limit remain unqualified.
## Phase 14 — Native Plugin, Instrument, and Effect Architecture
**Goal:** Provide a stable internal extension interface before hosting external plugins.