Merge Phase D3: persist ViewModeModel in project ext state
This commit is contained in:
@@ -163,10 +163,46 @@ void ReaSamplerSession::saveToActiveProject() {
|
||||
const std::string json = bank_.serialize();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
kProjExtIndexKey, json.c_str());
|
||||
|
||||
// Additive: the Design-View model rides alongside the bank in its own key.
|
||||
// Independent write — does not disturb the bank_index above.
|
||||
const std::string viewJson = view_.serialize();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
kProjExtViewKey, viewJson.c_str());
|
||||
|
||||
MarkProjectDirty(static_cast<ReaProject*>(proj));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Load the Design-View model from a project's view_state key, or return a fresh
|
||||
// default. An absent/empty key (older project with no view state) yields a
|
||||
// default-constructed model (Arrange + Design seeded, active = Arrange) — graceful,
|
||||
// never a crash. Malformed JSON is warned and also falls back to default, mirroring
|
||||
// the bank's malformed-index handling. The whole model round-trips: modes,
|
||||
// membership, show-both, snapshots, and active mode all ride inside the one blob.
|
||||
ViewModeModel loadViewModel(ReaProject* proj) {
|
||||
if (!proj) return ViewModeModel{};
|
||||
const std::string viewJson =
|
||||
getProjExtStateString(proj, kProjExtNamespace, kProjExtViewKey);
|
||||
if (viewJson.empty()) return ViewModeModel{}; // no stored view state -> default
|
||||
std::optional<ViewModeModel> loaded = ViewModeModel::deserialize(viewJson);
|
||||
if (!loaded) {
|
||||
ShowConsoleMsg("ReaSampler: stored view state is malformed — ignoring.\n");
|
||||
return ViewModeModel{};
|
||||
}
|
||||
return std::move(*loaded);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ReaSamplerSession::loadFromProject(void* proj, const std::string& projectDir) {
|
||||
// The view model is restored on EVERY load path (peer-symmetry with the bank
|
||||
// reset below): switching to a project with no view state must clear stale
|
||||
// in-memory state, not inherit the previous project's. D3 restores MODEL STATE
|
||||
// only — no visibility/processing is applied here (that is D4).
|
||||
view_ = loadViewModel(static_cast<ReaProject*>(proj));
|
||||
|
||||
if (!proj) {
|
||||
bank_ = BankIndex{};
|
||||
return;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "bank_model.h"
|
||||
#include "view_mode_model.h"
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
@@ -31,6 +32,12 @@ inline constexpr const char* kProjExtNamespace = "reasampler";
|
||||
// serialized BankIndex). FOREVER-STABLE for the same reason.
|
||||
inline constexpr const char* kProjExtIndexKey = "bank_index";
|
||||
|
||||
// The ext-state key the Design-View ViewModeModel JSON is stored under (one key
|
||||
// holds the whole serialized model: modes + membership + show-both + snapshots +
|
||||
// active mode). Distinct from kProjExtIndexKey — one namespace, two keys.
|
||||
// FOREVER-STABLE: changing it orphans every already-saved project's view state.
|
||||
inline constexpr const char* kProjExtViewKey = "view_state";
|
||||
|
||||
// The ext-state key holding a GUID we mint per project to establish CONTENT-BASED
|
||||
// project identity (REAPER exposes no stable per-project GUID). poll() uses it to
|
||||
// tell a genuine Save-As (same GUID, new .rpp path) apart from a project switch
|
||||
@@ -62,6 +69,13 @@ public:
|
||||
BankIndex& bank() { return bank_; }
|
||||
const BankIndex& bank() const { return bank_; }
|
||||
|
||||
// The in-memory Design-View model. The view/action layer mutates it (tag,
|
||||
// toggle, snapshot); persist serializes it on save and replaces it on project
|
||||
// load — exactly as it treats the bank. D3 persists MODEL STATE only; applying
|
||||
// visibility/processing (reapply-on-open) is D4's job, not this member's.
|
||||
ViewModeModel& view() { return view_; }
|
||||
const ViewModeModel& view() const { return view_; }
|
||||
|
||||
// Serialize the current bank to the active project's ext state (namespace
|
||||
// "reasampler"). Non-destructive beyond writing our own ext-state key. Safe
|
||||
// to call when there is no active/saved project (it no-ops).
|
||||
@@ -75,6 +89,11 @@ public:
|
||||
private:
|
||||
BankIndex bank_;
|
||||
|
||||
// The Design-View model. Default-constructed = Arrange + Design seeded, active
|
||||
// = Arrange; loadFromProject leaves this default when a project has no stored
|
||||
// view_state (older project), so an absent key is graceful, not a crash.
|
||||
ViewModeModel view_;
|
||||
|
||||
// The project identity last observed by poll(), used to detect load/Save-As.
|
||||
// Identity is the GUID we mint per project (kProjExtGuidKey), NOT the raw
|
||||
// ReaProject* pointer — see the class comment for why. The .rpp path is
|
||||
|
||||
Reference in New Issue
Block a user