/* * BridgeWrapper.h * --------------- * Purpose: VST plugin bridge wrapper (host side) * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #pragma once #include "openmpt/all/BuildSettings.hpp" #ifdef MPT_WITH_VST #include "BridgeCommon.h" #include "../common/ComponentManager.h" OPENMPT_NAMESPACE_BEGIN struct VSTPluginLib; enum PluginArch : int { PluginArch_unknown = 0, PluginArch_x86 = 32, PluginArch_amd64 = 64, PluginArch_arm = 128 + 32, PluginArch_arm64 = 128 + 64, }; std::size_t GetPluginArchPointerSize(PluginArch arch); enum class Generation { Legacy, Modern, }; class ComponentPluginBridge : public ComponentBase { public: enum Availability { AvailabilityUnknown = 0, AvailabilityOK = 1, AvailabilityMissing = -1, AvailabilityWrongVersion = -2, }; private: const PluginArch arch; const Generation generation; mpt::PathString exeName; Availability availability = AvailabilityUnknown; protected: ComponentPluginBridge(PluginArch arch, Generation generation); protected: bool DoInitialize() override; public: Availability GetAvailability() const { return availability; } mpt::PathString GetFileName() const { return exeName; } }; class ComponentPluginBridge_x86 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridge_x86, "PluginBridge-x86") public: ComponentPluginBridge_x86() : ComponentPluginBridge(PluginArch_x86, Generation::Modern) { } }; class ComponentPluginBridgeLegacy_x86 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridgeLegacy_x86, "PluginBridgeLegacy-x86") public: ComponentPluginBridgeLegacy_x86() : ComponentPluginBridge(PluginArch_x86, Generation::Legacy) { } }; class ComponentPluginBridge_amd64 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridge_amd64, "PluginBridge-amd64") public: ComponentPluginBridge_amd64() : ComponentPluginBridge(PluginArch_amd64, Generation::Modern) { } }; class ComponentPluginBridgeLegacy_amd64 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridgeLegacy_amd64, "PluginBridgeLegacy-amd64") public: ComponentPluginBridgeLegacy_amd64() : ComponentPluginBridge(PluginArch_amd64, Generation::Legacy) { } }; #if defined(MPT_WITH_WINDOWS10) class ComponentPluginBridge_arm : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridge_arm, "PluginBridge-arm") public: ComponentPluginBridge_arm() : ComponentPluginBridge(PluginArch_arm, Generation::Modern) { } }; class ComponentPluginBridgeLegacy_arm : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridgeLegacy_arm, "PluginBridgeLegacy-arm") public: ComponentPluginBridgeLegacy_arm() : ComponentPluginBridge(PluginArch_arm, Generation::Legacy) { } }; class ComponentPluginBridge_arm64 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridge_arm64, "PluginBridge-arm64") public: ComponentPluginBridge_arm64() : ComponentPluginBridge(PluginArch_arm64, Generation::Modern) { } }; class ComponentPluginBridgeLegacy_arm64 : public ComponentPluginBridge { MPT_DECLARE_COMPONENT_MEMBERS(ComponentPluginBridgeLegacy_arm64, "PluginBridgeLegacy-arm64") public: ComponentPluginBridgeLegacy_arm64() : ComponentPluginBridge(PluginArch_arm64, Generation::Legacy) { } }; #endif // MPT_WITH_WINDOWS10 class BridgeWrapper : private BridgeCommon { protected: Event m_sigAutomation; MappedMemory m_oldProcessMem; // Helper struct for keeping track of auxiliary shared memory struct AuxMem { std::atomic used = false; std::atomic size = 0; MappedMemory memory; wchar_t name[64]; }; AuxMem m_auxMems[MSG_STACK_SIZE]; std::vector m_cachedProgNames; std::vector m_cachedParamInfo; std::vector m_cachedParamValues; int32 m_cachedProgNameStart = 0, m_cachedParamInfoStart = 0; bool m_isSettingProgram = false; Vst::ERect m_editRect; Vst::VstSpeakerArrangement m_speakers[2]; ComponentHandle pluginBridge_x86; ComponentHandle pluginBridgeLegacy_x86; ComponentHandle pluginBridge_amd64; ComponentHandle pluginBridgeLegacy_amd64; #if defined(MPT_WITH_WINDOWS10) ComponentHandle pluginBridge_arm; ComponentHandle pluginBridgeLegacy_arm; ComponentHandle pluginBridge_arm64; ComponentHandle pluginBridgeLegacy_arm64; #endif // MPT_WITH_WINDOWS10 Generation m_Generation = Generation::Modern; public: // Generic bridge exception class BridgeException : public std::exception { public: BridgeException(const char *str) : std::exception(str) { } BridgeException() { } }; class BridgeNotFoundException : public BridgeException { }; // Exception from bridge process class BridgeRemoteException { protected: wchar_t *str; public: BridgeRemoteException(const wchar_t *str_) : str(_wcsdup(str_)) { } BridgeRemoteException(const BridgeRemoteException &) = delete; BridgeRemoteException & operator=(const BridgeRemoteException &) = delete; ~BridgeRemoteException() { free(str); } const wchar_t *what() const { return str; } }; public: static PluginArch GetNativePluginBinaryType(); static PluginArch GetPluginBinaryType(const mpt::PathString &pluginPath); static bool IsPluginNative(const mpt::PathString &pluginPath) { return GetPluginBinaryType(pluginPath) == GetNativePluginBinaryType(); } static uint64 GetFileVersion(const WCHAR *exePath); static Vst::AEffect *Create(const VSTPluginLib &plugin, bool forceLegacy); protected: BridgeWrapper(); ~BridgeWrapper(); bool Init(const mpt::PathString &pluginPath, Generation bridgeGeneration, BridgeWrapper *sharedInstace); void ParseNextMessage(int msgID); void DispatchToHost(DispatchMsg &msg); bool SendToBridge(BridgeMessage &sendMsg); void SendAutomationQueue(); AuxMem *GetAuxMemory(uint32 size); static intptr_t VSTCALLBACK DispatchToPlugin(Vst::AEffect *effect, Vst::VstOpcodeToPlugin opcode, int32 index, intptr_t value, void *ptr, float opt); intptr_t DispatchToPlugin(Vst::VstOpcodeToPlugin opcode, int32 index, intptr_t value, void *ptr, float opt); static void VSTCALLBACK SetParameter(Vst::AEffect *effect, int32 index, float parameter); void SetParameter(int32 index, float parameter); static float VSTCALLBACK GetParameter(Vst::AEffect *effect, int32 index); float GetParameter(int32 index); static void VSTCALLBACK Process(Vst::AEffect *effect, float **inputs, float **outputs, int32 sampleFrames); static void VSTCALLBACK ProcessReplacing(Vst::AEffect *effect, float **inputs, float **outputs, int32 sampleFrames); static void VSTCALLBACK ProcessDoubleReplacing(Vst::AEffect *effect, double **inputs, double **outputs, int32 sampleFrames); template void BuildProcessBuffer(ProcessMsg::ProcessType type, int32 numInputs, int32 numOutputs, buf_t **inputs, buf_t **outputs, int32 sampleFrames); static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); }; OPENMPT_NAMESPACE_END #endif // MPT_WITH_VST