Phase 18: preserve portable project media paths and verify format migrations
This commit is contained in:
parent
440e98f2b5
commit
1369e4d463
15 changed files with 329 additions and 13 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# Project format v5 (reads v1/v2/v3/v4)
|
||||
# Project format v7 (reads v1–v6)
|
||||
|
||||
Phases 5–15 use a bounded text format implemented in C99 without a parser library.
|
||||
The extension is `.xtc`. File operations run exclusively on the control thread.
|
||||
|
|
@ -12,7 +12,7 @@ Fields use ASCII spaces. Integers are unsigned decimal, without signs.
|
|||
Counts determine the number of subsequent records:
|
||||
|
||||
```text
|
||||
XTC_PROJECT 5
|
||||
XTC_PROJECT 7
|
||||
APP 0 1 0
|
||||
TEMPO 120000
|
||||
IDS 1 1
|
||||
|
|
@ -82,8 +82,8 @@ node types 1..4, migrating their clips to empty asset paths. Version 2 accepts
|
|||
node types 1..5 and ASSET records. Both migrate to MIDI=0 and no notes.
|
||||
Version 3 accepts instrument nodes and MIDI/NOTES records. Versions 1–3 migrate
|
||||
all tracks to unity gain, centered pan, mute/solo off and no automation.
|
||||
Saving always writes v5. Unknown versions are rejected without replacing the destination; older
|
||||
applications cannot read v5. Migration and maximum-path roundtrips are tested.
|
||||
Saving always writes v7. Unknown versions are rejected without replacing the destination; older
|
||||
applications cannot read v7. Migration and maximum-path roundtrips are tested.
|
||||
|
||||
## Ownership and failures
|
||||
|
||||
|
|
@ -148,3 +148,43 @@ port/tick pairs, nonfinite values, unknown control ports and ticks beyond the
|
|||
project limit are rejected. Loaded plugin tempo comes from TEMPO. Range and
|
||||
discrete-mode compatibility are checked on control-thread compilation. Versions
|
||||
1–5 migrate with empty plugin lanes. See CONTROL.md for timing/ordering.
|
||||
|
||||
## Phase 18: version 7 and project folders
|
||||
|
||||
Current writer emits v7; readers migrate v1–v6. Record ordering and field bounds
|
||||
are otherwise unchanged from v6. v7 ASSET may contain a relative path, interpreted
|
||||
against the actual containing directory of the named project file (resolved on
|
||||
the control thread), never the launch working directory. After loading, all core
|
||||
asset references are absolute, including missing media. Media inside the save
|
||||
folder are written relative; references outside remain absolute. Save As resolves
|
||||
against its new folder and preserves media identity rather than rebasing it by
|
||||
accident. Copy/move a project folder together with its referenced media to retain
|
||||
portability. Saving does not copy assets: import/record into that folder first.
|
||||
Plugin binaries remain trusted absolute module references, not bundled resources.
|
||||
|
||||
Empty assets still use `-`. Paths exclude embedded NUL/control bytes and must fit
|
||||
511 bytes after resolution; overly long resolved references fail transactionally.
|
||||
Relative references can name outside the folder using ordinary POSIX semantics;
|
||||
this is not a sandbox. Symlinks follow filesystem behavior, so portability requires
|
||||
moving their targets too. Old formats continue to require absolute media paths.
|
||||
No unknown version/node/record is silently discarded; unsupported versions/types
|
||||
or malformed/trailing data reject the candidate and retain the current project.
|
||||
Parsing never opens media/plugins or constructs an audio engine.
|
||||
|
||||
Save validates the complete model, writes/fsyncs a same-folder temporary, closes
|
||||
it, atomically renames it, then fsyncs the containing directory. Failures before
|
||||
rename retain the old destination. A directory sync failure *after* rename reports
|
||||
I/O error but the new complete file may already be present: inspect/reopen it;
|
||||
there is no rollback across that durability boundary. Filesystem/hardware power
|
||||
loss guarantees still depend on the underlying storage. Recording destinations
|
||||
have their separate no-clobber policy; ordinary project Save intentionally replaces
|
||||
the selected document. In-memory models and the existing destination are preserved
|
||||
on load failure. No automatic unknown-field stripping or media deletion occurs.
|
||||
|
||||
`make test-portability test test-plugins test-recovery test-recording` covers checked-in
|
||||
v1–v6 fixtures (including missing v5/v6 plugins), v7 exact roundtrips, moved-folder
|
||||
playback from a different cwd, missing media retention, unknown records, every
|
||||
truncation and deterministic byte mutations, malformed plugin metadata, interrupted
|
||||
writers and write-limit failures. ASan/UBSan/static analysis additionally audit the
|
||||
bounded parser. This is regression/fault-injection coverage, not exhaustive fuzzing
|
||||
or a claim of power-cut qualification.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue