fix: layer GUID-primary project identity so reopened/new projects reload the bank
classifyProjectTransition now checks the stored GUID first, then the pointer, fixing the w10 regression where a recycled ReaProject* address stopped the bank reloading. poll()'s fork re-GUID gate is bound to !sameProjectObject. Full transition matrix pinned in tests.
This commit is contained in:
+13
-11
@@ -53,13 +53,14 @@ inline constexpr const char* kProjExtGuidKey = "project_guid";
|
||||
// * project load -> load the index from ext state, resolve bank paths
|
||||
// * Save-As (new dir) -> relocate the bank folder under the new .rpp
|
||||
//
|
||||
// Identity rests on the live ReaProject* pointer FIRST (a genuine Save-As is one
|
||||
// object saved to a new path — same pointer; a tab-switch/open is a different
|
||||
// object), with a minted GUID as a SECONDARY signal to survive pointer *reuse*
|
||||
// (REAPER recycles a closed project's address). The pointer is what distinguishes
|
||||
// a Save-As from a switch between two FORKED siblings that share a copied GUID on
|
||||
// disk (the W10 data-integrity defect: dropping the pointer let a fork tab-switch
|
||||
// masquerade as a Save-As and clobber a bank).
|
||||
// Identity is layered GUID-PRIMARY: the minted GUID (content-based identity of
|
||||
// record, immune to REAPER recycling a closed project's ReaProject* address) is
|
||||
// checked FIRST, and the live pointer disambiguates only the same-GUID case — a
|
||||
// forked sibling (same GUID, different object -> Load) vs a genuine Save-As (same
|
||||
// GUID, same object, new path -> relocate). GUID-first catches pointer recycling
|
||||
// (a reopened/new project reusing the previous address with a different GUID — the
|
||||
// W12 defect that stopped the bank reloading); the pointer catches forks (Save-As
|
||||
// copies our GUID onto a distinct object — the W10 defect that clobbered a bank).
|
||||
//
|
||||
// The bank itself is exposed for the capture/action layer to mutate; persist
|
||||
// only reads it on save and replaces it on load.
|
||||
@@ -110,10 +111,11 @@ private:
|
||||
ViewModeModel view_;
|
||||
|
||||
// The project identity last observed by poll(), used to detect load/Save-As.
|
||||
// The pointer is the PRIMARY signal (same object across ticks = a candidate
|
||||
// Save-As; different object = a switch/open, never a relocate). The GUID and
|
||||
// path travel alongside: the GUID distinguishes pointer *reuse* and drives
|
||||
// forked-sibling re-divergence; the path tells a Save-As from an idle tick.
|
||||
// The GUID is the PRIMARY signal (a different stored GUID = a different project
|
||||
// of record = Load, immune to pointer recycling). The pointer disambiguates the
|
||||
// same-GUID case (different object = forked sibling -> Load; same object + new
|
||||
// path -> Save-As) and drives forked-sibling re-divergence; the path tells a
|
||||
// Save-As from an idle tick.
|
||||
// Held as void* so the header stays REAPER-free; it is a compared-only opaque
|
||||
// handle (never dereferenced), so a stale/recycled address is harmless.
|
||||
void* lastProject_ = nullptr; // last active ReaProject* (opaque; compare only)
|
||||
|
||||
Reference in New Issue
Block a user