81 lines
3.1 KiB
C++
81 lines
3.1 KiB
C++
// See view_reconcile.h. Compiled into the reaper_reasampler module; includes
|
|
// reaper_plugin_functions.h without REAPERAPI_IMPLEMENT (main.cpp owns that).
|
|
// The decision is pure (header, test_view_reconcile.cpp); this file owns the memo's
|
|
// lifetime and the writes.
|
|
|
|
#include "shell/view/view_reconcile.h"
|
|
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include "shell/view/view_park.h" // trackFlagParm / writeIfChanged
|
|
#include "shell/view/view_tracks.h"
|
|
|
|
#define REAPERAPI_MINIMAL
|
|
#define REAPERAPI_WANT_EnumProjects
|
|
#define REAPERAPI_WANT_TrackList_AdjustWindows
|
|
#define REAPERAPI_WANT_Undo_BeginBlock2
|
|
#define REAPERAPI_WANT_Undo_EndBlock2
|
|
#define REAPERAPI_WANT_UpdateArrange
|
|
#define REAPERAPI_WANT_ValidatePtr2
|
|
#include "reaper_plugin_functions.h"
|
|
|
|
namespace reasampler {
|
|
|
|
namespace {
|
|
|
|
// What the last apply left driven, per project. Keyed by ReaProject*, COMPARE-ONLY
|
|
// and never dereferenced (the same discipline the panel's own project memos take): a
|
|
// closed project's pointer must never be followed, only found unequal or used as a
|
|
// map key. A project absent here gets no repair — the tool has no account of driving
|
|
// anything there, so it has no opinion. Never pruned on project close: churn is a
|
|
// handful of entries per session, cheap enough that a close hook would cost more than
|
|
// it saves. One slot used to serve every project; a tab-switch mid-session silently
|
|
// discarded whichever project's memo wasn't "current" — see planReconcilePerProject.
|
|
std::map<ReaProject*, view::AppliedState> g_applied;
|
|
|
|
} // namespace
|
|
|
|
void noteAppliedState(ReaProject* proj, const ViewModeModel& model) {
|
|
ReaProject* const project = proj ? proj : EnumProjects(-1, nullptr, 0);
|
|
g_applied[project] = view::appliedState(model);
|
|
}
|
|
|
|
void reconcileAppliedFlags(ViewModeModel& model, ReaProject* proj) {
|
|
ReaProject* const project = proj ? proj : EnumProjects(-1, nullptr, 0);
|
|
if (!ValidatePtr2(nullptr, project, "ReaProject*")) return;
|
|
|
|
const view::AppliedState reloaded = view::appliedState(model);
|
|
const ProjectReconcileResult result = planReconcilePerProject(g_applied, project, reloaded);
|
|
|
|
// Adopted whether or not anything is written: from here the memo describes the
|
|
// project as it now stands, so a second reload cannot replay a repair that has
|
|
// already happened over values the user has since changed.
|
|
g_applied[project] = result.newEntry;
|
|
if (result.ops.empty()) return;
|
|
|
|
TrackHandles handleByGuid;
|
|
readFolderEntries(project, handleByGuid);
|
|
const TrackByGuid trackByGuid = indexHandles(handleByGuid);
|
|
|
|
bool wrote = false;
|
|
Undo_BeginBlock2(project);
|
|
{
|
|
UiRefreshHold uiHold;
|
|
for (const TrackFlagOp& op : result.ops) {
|
|
MediaTrack* tr = resolve(trackByGuid, op.guid);
|
|
if (!tr) continue; // stale/deleted GUID — prune
|
|
if (writeIfChanged(tr, trackFlagParm(op.flag), static_cast<double>(op.value)))
|
|
wrote = true;
|
|
}
|
|
}
|
|
Undo_EndBlock2(project, "", 0); // discard form — see the header
|
|
|
|
if (wrote) {
|
|
TrackList_AdjustWindows(false); // tracks reappearing owe the full relayout
|
|
UpdateArrange();
|
|
}
|
|
}
|
|
|
|
} // namespace reasampler
|