Files
reasampler/src/shell/view/view_solo.cpp
T
daniel f2cdf676f3 Ψ-W1-T2 review remediation: solo restore drops on visible-in-target, not parked; N-mode segments read dead when unroutable
Fixes a hidden-parent solo replay that could silence the mix. Also closes the N-mode segment silent no-op, amends the invariant comment, trims view.cpp under 600 lines, hedges two SDK inferences, drops a dead null-check.
2026-08-01 20:13:10 -04:00

62 lines
2.2 KiB
C++

// See view_solo.h. Compiled into the reaper_reasampler module; includes
// reaper_plugin_functions.h without REAPERAPI_IMPLEMENT (main.cpp owns that).
#include "shell/view/view_solo.h"
#include <map>
#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_GetMediaTrackInfo_Value
#define REAPERAPI_WANT_SetMediaTrackInfo_Value
#include "reaper_plugin_functions.h"
namespace reasampler {
namespace {
// SDK: int, 0=not soloed, 1=soloed, 2=soloed in place, 5=safe soloed,
// 6=safe soloed in place. Documented under SetMediaTrackInfo_Value with no
// read-only marker (unlike B_RECMON_IN_EFFECT in the same list), so it is settable.
constexpr const char* kSoloParm = "I_SOLO";
} // namespace
std::vector<view::TrackSolo> readTrackSolos(const TrackHandles& handles) {
std::vector<view::TrackSolo> live;
live.reserve(handles.size());
for (const auto& [guid, tr] : handles) {
if (!tr) continue;
live.push_back(view::TrackSolo{
guid, static_cast<int>(GetMediaTrackInfo_Value(tr, kSoloParm))});
}
return live;
}
void applySoloOps(const TrackHandles& handles, const std::vector<view::SoloOp>& ops) {
if (ops.empty()) return; // the common case: nothing soloed, no project write
std::map<std::string, int> byGuid;
for (const view::SoloOp& op : ops) byGuid[op.guid] = op.value;
for (const auto& [guid, tr] : handles) {
if (!tr) continue;
auto it = byGuid.find(guid);
if (it == byGuid.end()) continue;
SetMediaTrackInfo_Value(tr, kSoloParm, static_cast<double>(it->second));
}
}
void clearTrackSolos(const TrackHandles& handles, const std::map<std::string, int>& soloed) {
std::vector<view::SoloOp> ops;
ops.reserve(soloed.size());
for (const auto& entry : soloed) ops.push_back(view::SoloOp{entry.first, 0});
applySoloOps(handles, ops);
}
void restoreTrackSolos(const TrackHandles& handles,
const std::map<std::string, int>& cached,
const std::set<std::string>& liveGuids,
const std::set<std::string>& visibleGuids) {
applySoloOps(handles, view::planSoloRestore(cached, liveGuids, visibleGuids));
}
} // namespace reasampler