238 lines
7.2 KiB
C
238 lines
7.2 KiB
C
|
/*
|
||
|
* 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<bool> used = false;
|
||
|
std::atomic<uint32> size = 0;
|
||
|
MappedMemory memory;
|
||
|
wchar_t name[64];
|
||
|
};
|
||
|
AuxMem m_auxMems[MSG_STACK_SIZE];
|
||
|
|
||
|
std::vector<char> m_cachedProgNames;
|
||
|
std::vector<ParameterInfo> m_cachedParamInfo;
|
||
|
std::vector<float> m_cachedParamValues;
|
||
|
int32 m_cachedProgNameStart = 0, m_cachedParamInfoStart = 0;
|
||
|
|
||
|
bool m_isSettingProgram = false;
|
||
|
|
||
|
Vst::ERect m_editRect;
|
||
|
Vst::VstSpeakerArrangement m_speakers[2];
|
||
|
|
||
|
ComponentHandle<ComponentPluginBridge_x86> pluginBridge_x86;
|
||
|
ComponentHandle<ComponentPluginBridgeLegacy_x86> pluginBridgeLegacy_x86;
|
||
|
ComponentHandle<ComponentPluginBridge_amd64> pluginBridge_amd64;
|
||
|
ComponentHandle<ComponentPluginBridgeLegacy_amd64> pluginBridgeLegacy_amd64;
|
||
|
#if defined(MPT_WITH_WINDOWS10)
|
||
|
ComponentHandle<ComponentPluginBridge_arm> pluginBridge_arm;
|
||
|
ComponentHandle<ComponentPluginBridgeLegacy_arm> pluginBridgeLegacy_arm;
|
||
|
ComponentHandle<ComponentPluginBridge_arm64> pluginBridge_arm64;
|
||
|
ComponentHandle<ComponentPluginBridgeLegacy_arm64> 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<typename buf_t>
|
||
|
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
|