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.