Merge Θ-W1-T2: fix drag-out audio loss and FX-container drops, re-home ingest
This commit is contained in:
@@ -48,4 +48,10 @@ PathList assemblePathList(const std::vector<ResolvedSample>& resolved) {
|
||||
return out;
|
||||
}
|
||||
|
||||
OsHandoff decideOsHandoff(const std::vector<std::string>& paths) {
|
||||
OsHandoff out;
|
||||
out.handOffToOs = !paths.empty();
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace reasampler::ui
|
||||
|
||||
@@ -69,4 +69,21 @@ struct PathList {
|
||||
// exact-string — the shell normalizes case/slashes upstream if it wants Windows-style dedup.
|
||||
PathList assemblePathList(const std::vector<ResolvedSample>& resolved);
|
||||
|
||||
// --- OS hand-off ordering -----------------------------------------------------
|
||||
|
||||
// Whether an empty/unresolvable payload should hand off to the OS at all. This decides ONLY
|
||||
// the empty-payload third of the failure space — an unresolvable payload must leave the
|
||||
// internal drag live rather than winding it down (release capture, clear drag state) for a
|
||||
// hand-off that then never happens, which reads to the user as "the drag did nothing, try
|
||||
// again". A resolved-but-OS-not-ready hand-off (OLE unavailable, HDROP build failure) is a
|
||||
// separate, shell-side readiness gate (drag_out_win::canInitiateDragOut) checked BEFORE the
|
||||
// shell tears down internal drag state — this struct does not model that path.
|
||||
struct OsHandoff {
|
||||
bool handOffToOs = false; // true: wind down internal drag state, then start the OS drag
|
||||
};
|
||||
|
||||
// Decides the hand-off from the assembled path list. Empty (everything stale/unresolvable)
|
||||
// means the internal drag stays live rather than dying half-torn-down.
|
||||
OsHandoff decideOsHandoff(const std::vector<std::string>& paths);
|
||||
|
||||
} // namespace reasampler::ui
|
||||
|
||||
@@ -76,6 +76,17 @@ std::vector<std::uint8_t> buildInstrumentDropPreset(const std::string& sampleId)
|
||||
return buildVstPresetBytes(vstClassIdHex(), instrumentDropStateBytes(sampleId));
|
||||
}
|
||||
|
||||
DropOutcome decideDropOutcome(const DropAttempt& attempt) {
|
||||
DropOutcome out;
|
||||
if (attempt.addedFxIndex < 0) return out; // add failed — nothing exists to roll back
|
||||
if (!attempt.presetApplied) {
|
||||
out.rollbackFxIndex = attempt.addedFxIndex;
|
||||
return out;
|
||||
}
|
||||
out.loaded = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
bool infoNamesFxHotspot(const std::string& info) {
|
||||
// See the header contract for the prefix rule and the embed-strip exclusion.
|
||||
auto startsWith = [&info](const char* p) { return info.rfind(p, 0) == 0; };
|
||||
|
||||
@@ -68,4 +68,25 @@ bool infoNamesFxHotspot(const std::string& info);
|
||||
// assert the capture is selected. Not called by the shell.
|
||||
std::vector<std::uint8_t> instrumentDropStateBytes(const std::string& sampleId);
|
||||
|
||||
// --- All-or-nothing rollback --------------------------------------------------
|
||||
|
||||
// What the shell observed while executing one drop, reduced to the two REAPER
|
||||
// results the contract turns on.
|
||||
struct DropAttempt {
|
||||
int addedFxIndex = -1; // TrackFX_AddByName's return; < 0 = nothing was created
|
||||
bool presetApplied = false; // TrackFX_SetPreset's return
|
||||
};
|
||||
|
||||
// The verdict. `rollbackFxIndex >= 0` obliges the caller to TrackFX_Delete it before
|
||||
// returning — an instance whose capture never landed must not survive the drop.
|
||||
struct DropOutcome {
|
||||
bool loaded = false;
|
||||
int rollbackFxIndex = -1;
|
||||
};
|
||||
|
||||
// Pure so the contract is provable without a DAW: the rollback obligation is decided
|
||||
// here, not inline in the shell, and holds identically for every drop surface (FX
|
||||
// button, FX chain/container, Media-Explorer import).
|
||||
DropOutcome decideDropOutcome(const DropAttempt& attempt);
|
||||
|
||||
} // namespace reasampler::wire
|
||||
|
||||
Reference in New Issue
Block a user