// native_bridge/include/INativeInstrument.h #ifndef I_NATIVE_INSTRUMENT_H #define I_NATIVE_INSTRUMENT_H #include #include enum class InstrumentType { VST3, VST2, SOUNDFONT_SF2_SF3, SFZ }; class INativeInstrument { public: virtual ~INativeInstrument() = default; // Initialize Engine with Sample Rate and Buffer Size virtual bool init(double sampleRate, uint32_t maxBlockSize) = 0; // Select Bank and Program Change virtual void selectProgram(uint32_t channel, uint32_t bank, uint32_t program) = 0; // Dispatch MIDI Note On / Note Off events virtual void noteOn(uint32_t channel, uint32_t pitch, float velocity, uint32_t sampleOffset) = 0; virtual void noteOff(uint32_t channel, uint32_t pitch, uint32_t sampleOffset) = 0; // MIDI continuous controllers (A12): CC value, program change, 14-bit pitch bend virtual void controlChange(uint32_t channel, uint32_t cc, uint32_t value) = 0; virtual void programChange(uint32_t channel, uint32_t program) = 0; virtual void pitchBend(uint32_t channel, uint32_t bend14) = 0; // Open/close Native GUI window virtual bool openGUI(void* parentWindowHandle) = 0; // Headless engines (VST2 without an editor, SF2/SFZ): the bridge must // not create/reuse a window for them. virtual bool canOpenGUI() const { return true; } // Sandbox hosts whose child owns its own top-level window (sandbox VST2): // the bridge must not create a parent native window nor close other // editors — attachView(nullptr) just forwards the OPEN_GUI control. virtual bool ownsGuiWindow() const { return false; } virtual void closeGUI() = 0; // VST3 reopen-after-close: the bridge checks before openGUI whether the // instance must be rebuilt; while it is, the engine sets reloading=true // and the real-time loop skips processAudioBlock (teardown must not race // the audio thread — a reload terminates the VST while renderAll may be // inside processAudioBlock on the same instance). virtual bool needsReload() const { return false; } virtual void setReloading(bool /*on*/) {} // VST3: rebuild the plugin instance (terminate + loadPlugin) on the owning // apartment thread. The bridge calls it after tearing an editor down so the // audio loop never processes an instance whose editor was dropped without // view->removed(). Non-VST engines: no-op. virtual bool reload() { return true; } // VST3: split openGUI so instance teardown/reload runs on the owning // apartment thread while view->attached() may run on a temporary thread // with the channel worker pumping messages (see bridge main.cpp). virtual bool reloadForGUI() { return true; } virtual bool attachView(void* /*parentWindowHandle*/) { return false; } virtual void resizeView(int /*w*/, int /*h*/) {} // Periodic idle tick for attached editors (VST2 effEditIdle repaints; // others: no-op). Called on the UI worker's pump loop. virtual void guiIdle() {} // True while the editor view is attached (GUI window open). The bridge uses // it to dedupe repeated OPEN_GUI (frontend retry spam) — re-attaching a // view that is already attached corrupts plugins (Nexus createView→null). virtual bool hasAttachedView() const { return false; } // G0.4: serialize/restore the plugin preset across instance reloads // (GUI close/reopen). Non-VST engines: no-op (nothing to save). virtual void captureState() {} virtual void restoreState() {} // G2.1: serialize the current preset to a portable string for the state // file (VST3: base64 of captured component+controller state). Caller must // call captureState() first (VST3 buffers are refreshed there). Non-VST // engines: empty. virtual std::string serializeState() const { return std::string(); } // G2.3: replace the preset with a previously serialized one (VST3: // base64 of [4B BE compLen][component][4B BE ctrlLen][controller]). // Must be called after the instrument is loaded. Non-VST: no-op. virtual void loadSerializedState(const std::string& /*base64*/) {} // G2.1: last bank/program for a MIDI channel (SF2/SF3). Others: 0. virtual uint32_t bankOf(uint32_t channel) const { return 0; } virtual uint32_t programOf(uint32_t channel) const { return 0; } // Real-time Audio PCM Float32 rendering loop virtual void processAudioBlock(float* outputL, float* outputR, uint32_t numSamples) = 0; }; #endif // I_NATIVE_INSTRUMENT_H