Extend the park trust test to the FX chain, name the refused tracks, and stop reprinting an unchanged refusal
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "shell/view/view_fx_park.h"
|
||||
|
||||
#include <cstring> // strnlen — bounded read of GetTrackName's buffer
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -16,6 +17,7 @@
|
||||
#define REAPERAPI_WANT_EnumProjects
|
||||
#define REAPERAPI_WANT_GetMediaTrackInfo_Value
|
||||
#define REAPERAPI_WANT_GetTrack
|
||||
#define REAPERAPI_WANT_GetTrackName
|
||||
#define REAPERAPI_WANT_ShowConsoleMsg
|
||||
#define REAPERAPI_WANT_TrackFX_GetCount
|
||||
#define REAPERAPI_WANT_TrackFX_GetFXGUID
|
||||
@@ -33,6 +35,10 @@ FxParkQueue g_queue;
|
||||
ReaProject* g_owner = nullptr; // the project the pending intents were enqueued against
|
||||
bool g_draining = false;
|
||||
|
||||
// The last refusal report, so an unchanged one is not reprinted on every reapply.
|
||||
ReaProject* g_reportedOwner = nullptr;
|
||||
std::vector<std::string> g_reportedRefusals;
|
||||
|
||||
// Makes "one drain at a time" explicit rather than implied by the call sites.
|
||||
// RAII because an apply can throw and a stuck flag would silence the queue for
|
||||
// the rest of the session.
|
||||
@@ -98,14 +104,56 @@ std::string fxGuidString(MediaTrack* tr, int fx) {
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// ANY offline FX, not every one: a park offlines the whole chain, but a partial
|
||||
// undo or a half-finished hand recovery leaves some back online, and there is no
|
||||
// read that tells a park's leftover offline from one the user set. So the test
|
||||
// refuses in the direction that commits nothing false — the cost is a chain
|
||||
// carrying a hand-offlined plugin that the tool then declines to park.
|
||||
bool anyFxOffline(MediaTrack* tr) {
|
||||
const int fxCount = TrackFX_GetCount(tr);
|
||||
for (int fx = 0; fx < fxCount; ++fx)
|
||||
if (TrackFX_GetOffline(tr, fx)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// "Track N" for an unnamed track, matching REAPER's own convention (GetTrackName,
|
||||
// not P_NAME, for the same reason capture::trackName picks it). The buffer is
|
||||
// read bounded — the SDK documents no NUL within bufOut_sz. A track the report
|
||||
// cannot name still has to appear in it, so the read failing yields a placeholder
|
||||
// rather than dropping the entry.
|
||||
std::string trackDisplayName(MediaTrack* tr) {
|
||||
std::vector<char> buf(1024, '\0');
|
||||
if (!GetTrackName || !GetTrackName(tr, buf.data(), static_cast<int>(buf.size())))
|
||||
return "(name unavailable)";
|
||||
return std::string(buf.data(), strnlen(buf.data(), buf.size()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<int> readParkFlagValues(MediaTrack* tr, const std::vector<TrackFlagOp>& parkFlags) {
|
||||
std::vector<int> live;
|
||||
live.reserve(parkFlags.size());
|
||||
for (const TrackFlagOp& op : parkFlags)
|
||||
live.push_back(static_cast<int>(GetMediaTrackInfo_Value(tr, trackFlagParm(op.flag))));
|
||||
return live;
|
||||
ParkAction decideParkForTrack(MediaTrack* tr, bool haveSnapshot,
|
||||
const std::vector<TrackFlagOp>& parkFlags) {
|
||||
if (haveSnapshot) return decidePark(true, false); // second term unread — skip the reads
|
||||
const bool flagsRead = parkFlagsAlreadyApplied(parkFlags, [tr](Flag f) {
|
||||
return static_cast<int>(GetMediaTrackInfo_Value(tr, trackFlagParm(f)));
|
||||
});
|
||||
return decidePark(false, chainReadsParked(flagsRead, anyFxOffline(tr)));
|
||||
}
|
||||
|
||||
void reportRefusedParks(ReaProject* proj, const std::vector<MediaTrack*>& refused) {
|
||||
ReaProject* const owner = proj ? proj : currentProject();
|
||||
|
||||
std::vector<std::string> names;
|
||||
names.reserve(refused.size());
|
||||
for (MediaTrack* tr : refused) names.push_back(trackDisplayName(tr));
|
||||
|
||||
if (owner == g_reportedOwner && names == g_reportedRefusals) return;
|
||||
g_reportedOwner = owner;
|
||||
g_reportedRefusals = names;
|
||||
|
||||
const std::string msg = describeRefusedParks(names);
|
||||
// "!SHOW:" so an unattended project-load reapply cannot force the console open
|
||||
// (reaper_plugin_functions.h:6536), same as the drain's drop report.
|
||||
if (!msg.empty()) ShowConsoleMsg(("!SHOW:" + msg).c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> liveFxGuids(MediaTrack* tr) {
|
||||
|
||||
Reference in New Issue
Block a user