Resolve ReaSampler 9000 samples against the instance's own project, not the focused tab

sampleRoots matches getReaperParent(3) among EnumProjects' open projects; every instrument sample read goes through an ordered root list (one root today) so a later temp-bank root slots in after it.
This commit is contained in:
2026-09-25 14:55:50 -04:00
parent c3e7556261
commit 0976ea13a8
11 changed files with 304 additions and 42 deletions
+41
View File
@@ -0,0 +1,41 @@
// sample_roots — where the instrument looks for a bank-relative sample: the directory of
// the project it LIVES IN, found by identity among the open projects, never the focused
// tab's. Pure: the shell enumerates REAPER's projects and reads files; this decides which
// project, which roots, and in what order.
#pragma once
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
namespace reasampler::instrument::map {
// One enumerated project: its identity (an opaque ReaProject*, compared, never
// dereferenced) and its .rpp path, empty for a never-saved project.
struct ProjectTab {
const void* project = nullptr;
std::string rppPath;
};
// The directory of the project whose identity is `own`; empty when `own` is null, is not
// among `open`, or was never saved. Deliberately no fallback to any other project: another
// project's bank folder can hold a same-named file, and playing it is the wrong-project
// bug this exists to close.
std::string ownProjectDir(const void* own, const std::vector<ProjectTab>& open);
// The roots a bank-relative path is tried against, in order. Only the project directory
// today — the ordered list is the seam a later root (tried after it) extends. Empty when
// there is no project directory, which every caller treats as nothing to play.
std::vector<std::string> sampleRootCandidates(const std::string& projectDir);
using FileReader = std::function<std::vector<std::uint8_t>(const std::string& path)>;
// The bytes of `relativePath` resolved under the first root whose read yields any (a read
// that comes back empty falls through to the next root); empty when none does.
std::vector<std::uint8_t> readFromFirstRoot(const std::vector<std::string>& roots,
const std::string& relativePath,
const FileReader& read);
} // namespace reasampler::instrument::map