S6: embedded TCP/MCP UI via IReaperUIEmbedInterface
Inline keymap/level strip drawn into REAPER's embed bitmap, reusing the LICE idiom. Pure embed_strip layout/hit-test (tested); processor exposes the embed interface off queryInterface and publishes an RT-safe block peak for the level.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "capture_paths.h" // resolveBankFile (shared M4 path resolution)
|
||||
#include "ext_keys.h" // kProjExtBanksKey (shared wire contract)
|
||||
#include "reasampler_editor.h"
|
||||
#include "reasampler_embed.h" // S6 embed shell + IReaperUIEmbedInterface (its iid DEF'd there)
|
||||
#include "sample_map.h" // selectSample, resolvePerformance, buildZonedKeymap, state (de)ser
|
||||
#include "wav_trim.h" // parseWavLayout, extractFloatFrames (shared WAV parse)
|
||||
|
||||
@@ -91,6 +92,23 @@ FUnknown* ReaSamplerProcessor::createInstance(void* /*context*/) {
|
||||
return static_cast<IAudioProcessor*>(new ReaSamplerProcessor());
|
||||
}
|
||||
|
||||
// Out-of-line so unique_ptr<ReaSamplerEmbed> sees the complete type here.
|
||||
ReaSamplerProcessor::~ReaSamplerProcessor() = default;
|
||||
|
||||
tresult PLUGIN_API ReaSamplerProcessor::queryInterface(const TUID iid, void** obj) {
|
||||
// S6: expose REAPER's inline-embed interface. REAPER queries the IEditController for
|
||||
// IReaperUIEmbedInterface (reaper_vst3_interfaces.h); hand it our lazily-created embed
|
||||
// shell. We own the shell (unique_ptr); the borrowed reference is valid because the
|
||||
// processor outlives it. All other iids fall through to the SDK's queryInterface.
|
||||
if (FUnknownPrivate::iidEqual(iid, IReaperUIEmbedInterface::iid)) {
|
||||
if (!embed_) embed_ = std::make_unique<ReaSamplerEmbed>(this);
|
||||
embed_->addRef();
|
||||
*obj = static_cast<IReaperUIEmbedInterface*>(embed_.get());
|
||||
return kResultOk;
|
||||
}
|
||||
return SingleComponentEffect::queryInterface(iid, obj);
|
||||
}
|
||||
|
||||
tresult PLUGIN_API ReaSamplerProcessor::initialize(FUnknown* context) {
|
||||
tresult result = SingleComponentEffect::initialize(context);
|
||||
if (result != kResultOk) return result;
|
||||
@@ -357,6 +375,16 @@ tresult PLUGIN_API ReaSamplerProcessor::process(ProcessData& data) {
|
||||
if (inst) {
|
||||
inst->engine.render(ch0, static_cast<std::size_t>(frames));
|
||||
}
|
||||
// Block peak (mono, pre-replicate) for the embedded strip's level indicator. A
|
||||
// single scan of ch0 + one relaxed atomic store — RT-safe (no alloc/IO/lock). The
|
||||
// UI thread reads it via embedActivityLevel(); a plain store is sufficient because
|
||||
// the readout is advisory (no ordering dependency on other state).
|
||||
float peak = 0.f;
|
||||
for (int32 i = 0; i < frames; ++i) {
|
||||
const float a = ch0[i] < 0.f ? -ch0[i] : ch0[i];
|
||||
if (a > peak) peak = a;
|
||||
}
|
||||
embedPeak_.store(peak, std::memory_order_relaxed);
|
||||
// Duplicate the mono render across the remaining output channels.
|
||||
for (int32 ch = 1; ch < out.numChannels; ++ch) {
|
||||
if (float* buf = out.channelBuffers32[ch]) {
|
||||
|
||||
Reference in New Issue
Block a user