fix: bake-answer messages stop asserting causes the classifier can't see

Rewords Cleared/Unanswered/ForeignRequest to name only observed facts and every live hypothesis instead of picking a winner; adds a guarded answeredOutcome accessor against a future unhandled BakeAnswerKind; folds an unreachable BakeScanKey/Context test state; fixes generation-stamp timing.
This commit is contained in:
2026-08-02 06:57:08 -04:00
parent 962ab64ef0
commit 7f3b00a646
6 changed files with 139 additions and 35 deletions
+31 -10
View File
@@ -154,14 +154,18 @@ BakeChainResult runBake(ReaSamplerProcessor& processor) {
static_cast<std::size_t>(audio.frameCount()), interleaved);
const std::string instanceGuid = processor.usageInstanceGuid();
const std::int64_t stamp = static_cast<std::int64_t>(std::time(nullptr));
// Named for what it is used for here — the staged file's own name, nothing else.
// `request.generation` below takes its OWN, later timestamp: kMaxRequestAgeSeconds
// is a budget measured from the write, and re-using this one would silently spend it
// on the WAV write that happens in between.
const std::int64_t stageStamp = static_cast<std::int64_t>(std::time(nullptr));
// OUTSIDE the bank folder, always: the bank holds indexed captures only, and a stray
// file there would read as a prune orphan.
std::error_code ec;
const fs::path stagedPath =
fs::temp_directory_path(ec) /
("reasampler_bake_" + instanceGuid + "_" + std::to_string(stamp) + ".wav");
("reasampler_bake_" + instanceGuid + "_" + std::to_string(stageStamp) + ".wav");
if (ec) return fail("no writable temp directory for the staged render");
const std::string staged = stagedPath.string();
StagedFileGuard stagedGuard(staged);
@@ -175,7 +179,10 @@ BakeChainResult runBake(ReaSamplerProcessor& processor) {
request.sourceDisplayName = sourceEntry->displayName;
request.ownUsageKey = usageKeyFor(instanceGuid);
request.rootNote = plan.note;
request.generation = stamp;
// Stamped here, immediately before the publish below — AFTER the WAV write above,
// which is what makes kMaxRequestAgeSeconds' budget (bake_wire.h) exclude staging
// time rather than eat into it.
request.generation = static_cast<std::int64_t>(std::time(nullptr));
const std::string key = bakeKeyFor(instanceGuid);
RequestKeyGuard keyGuard(bridge, key);
@@ -198,24 +205,38 @@ BakeChainResult runBake(ReaSamplerProcessor& processor) {
case wire::BakeAnswerKind::Unanswered:
return fail(
"the ReaSampler extension did not run the bake landing -- its action id "
"resolved but nothing read the request. Most likely the installed "
"extension is older than this plugin: reinstall it and restart REAPER");
"resolved but nothing read the request. Possible causes: the extension is "
"older than this plugin and does not know this action; REAPER deferred "
"running the action past this call returning (unverified -- see "
"reaper_bridge.h); the extension ran but could not read its own request "
"key on this pass; or the action name resolved to an id no currently "
"loaded extension actually handles. Reinstalling the extension and "
"restarting REAPER is worth trying, but is not the only possible fix");
case wire::BakeAnswerKind::Undecodable:
return fail(
"the extension answered in a format this plugin does not read -- the "
"extension and ReaSampler 9000 are from different builds");
case wire::BakeAnswerKind::Cleared:
return fail(
"the extension discarded the bake request as stale before answering it");
"the bake key came back empty -- either the request was cleared before "
"an answer was written, or this build could not read whatever was there");
case wire::BakeAnswerKind::ForeignRequest:
return fail(
"another ReaSampler 9000 instance is baking under this instance's key -- "
"the two were copied from one another; reload this one and retry");
"the bake key held a different pending request instead of an answer -- "
"unexpected given the bake's single-threaded call flow; if this recurs, "
"note the exact steps and file it");
case wire::BakeAnswerKind::ForeignOutcome:
return fail("the extension answered a different bake request");
}
// Set by construction on Answered (bake_wire.h states the invariant at BakeAnswer).
const BakeOutcome& outcome = *answer.outcome;
// wire::answeredOutcome is the guard, not switch exhaustiveness alone: the switch
// above has no `default`, so a future BakeAnswerKind enumerator it doesn't yet handle
// would otherwise fall through to a raw `*answer.outcome` deref with nothing set.
const BakeOutcome* outcomePtr = wire::answeredOutcome(answer);
if (!outcomePtr)
return fail(
"the extension's answer was not one this build recognizes -- the extension "
"and ReaSampler 9000 may be from different builds");
const BakeOutcome& outcome = *outcomePtr;
if (outcome.status != BakeStatus::Ok)
return fail(outcome.message.empty() ? std::string("the bake was refused")
: outcome.message);