feat(version): V4 beta-in-isolation channel via -DREASAMPLER_CHANNEL
Compile-time channel flag forks a fully isolated reaper_reasampler_beta (namespace, command-id prefix, action names, dock ident, -beta render) from one auditable app_version definition. Stable identity byte-unchanged.
This commit is contained in:
+25
-22
@@ -194,7 +194,7 @@ bool ReaSamplerSession::saveToActiveProject() {
|
||||
// Phase B: the whole book (pool as bank-zero + named banks) is authoritative and
|
||||
// rides in the `banks` key.
|
||||
const std::string banksJson = book_.serialize();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtBanksKey, banksJson.c_str());
|
||||
|
||||
// Retire the legacy single-bank `bank_index` key: SetProjExtState with an empty
|
||||
@@ -202,37 +202,40 @@ bool ReaSamplerSession::saveToActiveProject() {
|
||||
// realizes retirement concretely — after any save, a formerly-legacy project
|
||||
// carries `banks` and NO `bank_index`, and going forward the legacy key is never
|
||||
// written. Cheap and idempotent when the key is already absent.
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtIndexKey, "");
|
||||
|
||||
// Additive: the Design-View model rides alongside the banks in its own key.
|
||||
// Independent write — does not disturb the `banks` blob above.
|
||||
const std::string viewJson = view_.serialize();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtViewKey, viewJson.c_str());
|
||||
|
||||
// Additive: the docked panel's tail setting rides alongside in its own key, so the
|
||||
// tail choice travels inside the .rpp. Independent write — does not disturb the
|
||||
// bank_index or view_state above.
|
||||
const std::string tailJson = serializeTailSetting(tail_);
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtTailKey, tailJson.c_str());
|
||||
|
||||
// Additive: the owned-file manifest (Phase B B-cap) rides alongside in its own
|
||||
// `owned_files` key. Independent write — does not disturb the blobs above. Written
|
||||
// on EVERY save so a capture's manifest record survives Save / Save-As / reopen,
|
||||
// and so the manifest and the bank stay in lockstep on disk (both persisted by the
|
||||
// same saveToActiveProject the capture add-path calls).
|
||||
// same saveToActiveProject the capture add-path calls). Uses the channel-derived
|
||||
// namespace (projExtNamespace) like its sibling keys — V4 isolation applies here too.
|
||||
const std::string ownedJson = owned_.serialize();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtOwnedKey, ownedJson.c_str());
|
||||
|
||||
// Phase V (V1): stamp the WRITING version — the build producing this save — under the
|
||||
// version key, on the SAME seam as the keys above so the stamp and MarkProjectDirty
|
||||
// stay paired (no drifting ad-hoc SetProjExtState). appVersion() is the one CMake-
|
||||
// sourced constant; every save records the exact current build into the .rpp.
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
kProjExtVersionKey, appVersion().c_str());
|
||||
// Phase V (V1/V4): stamp the WRITING version — the build producing this save — under
|
||||
// the version key, on the SAME seam as the keys above so the stamp and MarkProjectDirty
|
||||
// stay paired (no drifting ad-hoc SetProjExtState). stampVersion() (NOT appVersion()) is
|
||||
// the NUMERIC TRIPLE ONLY on both channels — no "-beta" suffix — so the stamp parses as
|
||||
// Stamped on read-back and stays byte-identical to stable regardless of channel; the
|
||||
// channel is already carried by the isolated namespace (projExtNamespace) this writes to.
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtVersionKey, stampVersion().c_str());
|
||||
|
||||
MarkProjectDirty(static_cast<ReaProject*>(proj));
|
||||
return true;
|
||||
@@ -249,7 +252,7 @@ namespace {
|
||||
ViewModeModel loadViewModel(ReaProject* proj) {
|
||||
if (!proj) return ViewModeModel{};
|
||||
const std::string viewJson =
|
||||
getProjExtStateString(proj, kProjExtNamespace, kProjExtViewKey);
|
||||
getProjExtStateString(proj, projExtNamespace(), kProjExtViewKey);
|
||||
if (viewJson.empty()) return ViewModeModel{}; // no stored view state -> default
|
||||
std::optional<ViewModeModel> loaded = ViewModeModel::deserialize(viewJson);
|
||||
if (!loaded) {
|
||||
@@ -266,7 +269,7 @@ ViewModeModel loadViewModel(ReaProject* proj) {
|
||||
TailSetting loadTailSetting(ReaProject* proj) {
|
||||
if (!proj) return TailSetting{};
|
||||
const std::string tailJson =
|
||||
getProjExtStateString(proj, kProjExtNamespace, kProjExtTailKey);
|
||||
getProjExtStateString(proj, projExtNamespace(), kProjExtTailKey);
|
||||
if (tailJson.empty()) return TailSetting{}; // no stored setting -> default
|
||||
std::optional<TailSetting> loaded = deserializeTailSetting(tailJson);
|
||||
if (!loaded) {
|
||||
@@ -285,7 +288,7 @@ TailSetting loadTailSetting(ReaProject* proj) {
|
||||
OwnedFileManifest loadOwnedManifest(ReaProject* proj) {
|
||||
if (!proj) return OwnedFileManifest{};
|
||||
const std::string ownedJson =
|
||||
getProjExtStateString(proj, kProjExtNamespace, kProjExtOwnedKey);
|
||||
getProjExtStateString(proj, projExtNamespace(), kProjExtOwnedKey);
|
||||
if (ownedJson.empty()) return OwnedFileManifest{}; // no stored manifest -> empty
|
||||
std::optional<OwnedFileManifest> loaded = OwnedFileManifest::deserialize(ownedJson);
|
||||
if (!loaded) {
|
||||
@@ -329,7 +332,7 @@ void ReaSamplerSession::loadFromProject(void* proj, const std::string& projectDi
|
||||
// an error). getProjExtStateString returns "" for an absent key, which is exactly the
|
||||
// PreVersioning input classifyWritingVersion expects. proj == nullptr -> "" -> default.
|
||||
writingVersion_ = classifyWritingVersion(
|
||||
proj ? getProjExtStateString(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
proj ? getProjExtStateString(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtVersionKey)
|
||||
: std::string{});
|
||||
|
||||
@@ -347,7 +350,7 @@ void ReaSamplerSession::loadFromProject(void* proj, const std::string& projectDi
|
||||
// warning. A malformed `banks` degrades to an empty book and does NOT fall back to
|
||||
// the stale legacy key (which would resurrect superseded single-bank state).
|
||||
const std::string banksJson =
|
||||
getProjExtStateString(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
getProjExtStateString(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtBanksKey);
|
||||
if (!banksJson.empty()) {
|
||||
std::optional<BankBook> loaded = BankBook::deserialize(banksJson);
|
||||
@@ -362,7 +365,7 @@ void ReaSamplerSession::loadFromProject(void* proj, const std::string& projectDi
|
||||
// by BankBook's parse-time promotion. loadFromPersisted covers the legacy-or-
|
||||
// empty tail; passing "" for banksJson takes exactly that branch.
|
||||
const std::string legacyJson =
|
||||
getProjExtStateString(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
getProjExtStateString(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtIndexKey);
|
||||
book_ = BankBook::loadFromPersisted(std::string{}, legacyJson);
|
||||
}
|
||||
@@ -391,7 +394,7 @@ std::string ensureProjectGuid(void* proj, const std::string& rppPath,
|
||||
if (!proj || rppPath.empty()) return {}; // unsaved -> cannot store a GUID
|
||||
if (!currentGuid.empty()) return currentGuid;
|
||||
const std::string minted = genProjectGuidString();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtGuidKey, minted.c_str());
|
||||
return minted;
|
||||
}
|
||||
@@ -416,7 +419,7 @@ void ReaSamplerSession::poll() {
|
||||
void* proj = readActiveProject(rppPath);
|
||||
const std::string currentGuid =
|
||||
proj ? getProjExtStateString(static_cast<ReaProject*>(proj),
|
||||
kProjExtNamespace, kProjExtGuidKey)
|
||||
projExtNamespace(), kProjExtGuidKey)
|
||||
: std::string{};
|
||||
|
||||
if (!primed_) {
|
||||
@@ -482,7 +485,7 @@ void ReaSamplerSession::poll() {
|
||||
if (proj && !sameProjectObject && !currentGuid.empty() &&
|
||||
currentGuid == lastGuid_ && !rppPath.empty()) {
|
||||
const std::string fresh = genProjectGuidString();
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtGuidKey, fresh.c_str());
|
||||
MarkProjectDirty(static_cast<ReaProject*>(proj));
|
||||
loadFromProject(proj, projectDirOf(rppPath));
|
||||
@@ -521,7 +524,7 @@ void ReaSamplerSession::poll() {
|
||||
// to the new .rpp on the next normal save / close-prompt.
|
||||
const std::string fresh = genProjectGuidString();
|
||||
if (proj) {
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
|
||||
SetProjExtState(static_cast<ReaProject*>(proj), projExtNamespace(),
|
||||
kProjExtGuidKey, fresh.c_str());
|
||||
MarkProjectDirty(static_cast<ReaProject*>(proj));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user