diff --git a/src/common/communication.cpp b/src/common/communication.cpp index 53da8dea..7ce87563 100644 --- a/src/common/communication.cpp +++ b/src/common/communication.cpp @@ -1,8 +1,8 @@ #include "communication.h" intptr_t send_event(boost::asio::local::stream_protocol::socket& socket, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option, diff --git a/src/common/communication.h b/src/common/communication.h index 89f5ddaa..8e4d6cf1 100644 --- a/src/common/communication.h +++ b/src/common/communication.h @@ -73,8 +73,8 @@ using InputAdapter = bitsery::InputBufferAdapter; struct Event { using buffer_type = ArrayBuffer; - int32_t opcode; - int32_t index; + int opcode; + int index; // TODO: This is an intptr_t, if we want to support 32 bit Wine plugins all // of these these intptr_t types should be replace by `uint64_t` to // remain compatible with the Linux VST plugin. @@ -133,7 +133,7 @@ struct EventResult { struct Parameter { using buffer_type = ArrayBuffer<16>; - int32_t index; + int index; std::optional value; template @@ -204,14 +204,12 @@ void serialize(S& s, AEffect& plugin) { s.value4b(plugin.numInputs); s.value4b(plugin.numOutputs); s.value4b(plugin.flags); - - // These fields can contain some values that are rarely used and/or - // deprecated, but we should pass them along anyway - s.container1b(plugin.empty3); - s.value4b(plugin.unknown_float); - + s.value4b(plugin.initialDelay); + s.value4b(plugin.empty3a); + s.value4b(plugin.empty3b); + s.value4b(plugin.unkown_float); s.value4b(plugin.uniqueID); - s.container1b(plugin.unknown1); + s.value4b(plugin.version); } // I don't want to editor 'include/vestige/aeffectx.h`. That's why this type @@ -312,8 +310,8 @@ inline T read_object(Socket& socket) { * @relates passthrough_event */ intptr_t send_event(boost::asio::local::stream_protocol::socket& socket, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option, diff --git a/src/common/logging.cpp b/src/common/logging.cpp index 728a75cb..6eb9da08 100644 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -84,7 +84,7 @@ void Logger::log(const std::string& message) { *stream << formatted_message.str() << std::flush; } -void Logger::log_get_parameter(int32_t index) { +void Logger::log_get_parameter(int index) { if (BOOST_UNLIKELY(verbosity >= Verbosity::events)) { std::ostringstream message; message << ">> getParameter() " << index; @@ -102,7 +102,7 @@ void Logger::log_get_parameter_response(float value) { } } -void Logger::log_set_parameter(int32_t index, float value) { +void Logger::log_set_parameter(int index, float value) { if (BOOST_UNLIKELY(verbosity >= Verbosity::events)) { std::ostringstream message; message << ">> setParameter() " << index << " = " << value; @@ -118,8 +118,8 @@ void Logger::log_set_parameter_response() { } void Logger::log_event(bool is_dispatch, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, std::optional payload, float option) { diff --git a/src/common/logging.h b/src/common/logging.h index b0b9b9d4..37a08763 100644 --- a/src/common/logging.h +++ b/src/common/logging.h @@ -83,15 +83,15 @@ class Logger { // The following functions are for logging specific events, they are only // enabled for verbosity levels higher than 1 (i.e. `Verbosity::events`) - void log_get_parameter(int32_t index); + void log_get_parameter(int index); void log_get_parameter_response(float vlaue); - void log_set_parameter(int32_t index, float value); + void log_set_parameter(int index, float value); void log_set_parameter_response(); // If is_dispatch is true, then use opcode names from the plugin's dispatch // function. Otherwise use names for the host callback function opcodes. void log_event(bool is_dispatch, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, std::optional payload, float option); diff --git a/src/include/vestige/aeffectx.h b/src/include/vestige/aeffectx.h index e6e715a6..edfba549 100644 --- a/src/include/vestige/aeffectx.h +++ b/src/include/vestige/aeffectx.h @@ -22,20 +22,23 @@ * */ +// This version of the header was obtained from the Audacity project +// https://github.com/audacity/audacity/blob/5900c524928be07d620bd7bfe282d53f839811f8/src/effects/VST/aeffectx.h +// and it contains a few opcodes there were missing from the original LMMS +// header + #pragma once -#include - -// Calling convention +// Calling convention for Wine interoperability, not part of the original +// headerfrom the Audacity proejct #ifndef __WINE__ #define __cdecl #endif #define VST_CALL_CONV __cdecl -#define CCONST(a, b, c, d) \ - ((((int32_t)a) << 24) | (((int32_t)b) << 16) | (((int32_t)c) << 8) | \ - (((int32_t)d) << 0)) +#define CCONST(a, b, c, d) \ + ((((int)a) << 24) | (((int)b) << 16) | (((int)c) << 8) | (((int)d) << 0)) const int audioMasterAutomate = 0; const int audioMasterVersion = 1; @@ -90,15 +93,23 @@ const int audioMasterGetChunkFile = 48; // currently unused const int audioMasterGetInputSpeakerArrangement = 49; // currently unused const int effFlagsHasEditor = 1; -const int effFlagsCanReplacing = 1 << 4; // very likely -const int effFlagsIsSynth = 1 << 8; // currently unused +const int effFlagsCanReplacing = 1 << 4; // very likely +const int effFlagsProgramChunks = 1 << 5; // from Ardour +const int effFlagsIsSynth = 1 << 8; // currently unused const int effOpen = 0; -const int effClose = 1; // currently unused -const int effSetProgram = 2; // currently unused -const int effGetProgram = 3; // currently unused +const int effClose = 1; // currently unused +const int effSetProgram = 2; // currently unused +const int effGetProgram = 3; // currently unused +// The next one was gleaned from +// http://www.kvraudio.com/forum/viewtopic.php?p=1905347 +const int effSetProgramName = 4; const int effGetProgramName = 5; // currently unused -const int effGetParamName = 8; // currently unused +// The next two were gleaned from +// http://www.kvraudio.com/forum/viewtopic.php?p=1905347 +const int effGetParamLabel = 6; +const int effGetParamDisplay = 7; +const int effGetParamName = 8; // currently unused const int effSetSampleRate = 10; const int effSetBlockSize = 11; const int effMainsChanged = 12; @@ -107,59 +118,83 @@ const int effEditOpen = 14; const int effEditClose = 15; const int effEditIdle = 19; const int effEditTop = 20; -const int effSetChunk = 24; +const int effIdentify = + 22; // from http://www.asseca.org/vst-24-specs/efIdentify.html +const int effGetChunk = 23; // from Ardour +const int effSetChunk = 24; // from Ardour const int effProcessEvents = 25; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efCanBeAutomated.html +const int effCanBeAutomated = 26; +// The next one was gleaned from +// http://www.kvraudio.com/forum/viewtopic.php?p=1905347 +const int effGetProgramNameIndexed = 29; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efGetPlugCategory.html +const int effGetPlugCategory = 35; const int effGetEffectName = 45; +const int effGetParameterProperties = 56; // missing const int effGetVendorString = 47; const int effGetProductString = 48; const int effGetVendorVersion = 49; -const int effCanDo = 51; // currently unused +const int effCanDo = 51; // currently unused +// The next one was gleaned from http://www.asseca.org/vst-24-specs/efIdle.html +const int effIdle = 53; const int effGetVstVersion = 58; // currently unused +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efBeginSetProgram.html +const int effBeginSetProgram = 67; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efEndSetProgram.html +const int effEndSetProgram = 68; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efShellGetNextPlugin.html +const int effShellGetNextPlugin = 70; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efBeginLoadBank.html +const int effBeginLoadBank = 75; +// The next one was gleaned from +// http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html +const int effBeginLoadProgram = 76; + +// The next two were gleaned from +// http://www.kvraudio.com/forum/printview.php?t=143587&start=0 +const int effStartProcess = 71; +const int effStopProcess = 72; const int kEffectMagic = CCONST('V', 's', 't', 'P'); const int kVstLangEnglish = 1; const int kVstMidiType = 1; -const int kVstTransportChanged = 1; -const int kVstTransportPlaying = 1 << 1; -const int kVstTransportCycleActive = 1 << 2; -const int kVstTransportRecording = 1 << 3; // currently unused +const int kVstNanosValid = 1 << 8; const int kVstPpqPosValid = 1 << 9; const int kVstTempoValid = 1 << 10; const int kVstBarsValid = 1 << 11; const int kVstCyclePosValid = 1 << 12; const int kVstTimeSigValid = 1 << 13; -const int kVstSmpteValid = 1 << 14; // currently unused -const int kVstClockValid = 1 << 15; // currently unused +const int kVstSmpteValid = 1 << 14; // from Ardour +const int kVstClockValid = 1 << 15; // from Ardour -// currently unused -const int kVstSmpte24fps = 0; -const int kVstSmpte25fps = 1; -const int kVstSmpte2997fps = 2; -const int kVstSmpte30fps = 3; -const int kVstSmpte2997dfps = 4; -const int kVstSmpte30dfps = 5; -const int kVstSmpteFilm16mm = 6; // very likely -const int kVstSmpteFilm35mm = 7; // very likely -const int kVstSmpte239fps = 10; -const int kVstSmpte249fps = 11; -const int kVstSmpte599fps = 12; -const int kVstSmpte60fps = 13; +const int kVstTransportPlaying = 1 << 1; +const int kVstTransportCycleActive = 1 << 2; +const int kVstTransportChanged = 1; + +class RemoteVstPlugin; class VstMidiEvent { public: // 00 - int32_t type; + int type; // 04 - int32_t byteSize; + int byteSize; // 08 - int32_t deltaFrames; + int deltaFrames; // 0c? - int32_t flags; + int flags; // 10? - int32_t noteLength; + int noteLength; // 14? - int32_t noteOffset; + int noteOffset; // 18 char midiData[4]; // 1c? @@ -179,56 +214,87 @@ class VstEvent { class VstEvents { public: // 00 - int32_t numEvents; + int numEvents; // 04 void* reserved; // 08 VstEvent* events[1]; }; +// Not finished, neither really used +class VstParameterProperties { + public: + /* float stepFloat; + char label[64]; + int flags; + int minInteger; + int maxInteger; + int stepInteger; + char shortLabel[8]; + int category; + char categoryLabel[24]; + char empty[128];*/ + + float stepFloat; + float smallStepFloat; + float largeStepFloat; + char label[64]; + unsigned int flags; + unsigned int minInteger; + unsigned int maxInteger; + unsigned int stepInteger; + unsigned int largeStepInteger; + char shortLabel[8]; + unsigned short displayIndex; + unsigned short category; + unsigned short numParametersInCategory; + unsigned short reserved; + char categoryLabel[24]; + char future[16]; +}; + +#include + class AEffect { public: // Never use virtual functions!!! // 00-03 - int32_t magic; + int magic; // dispatcher 04-07 - intptr_t(VST_CALL_CONV* dispatcher)(AEffect*, - int32_t, - int32_t, - intptr_t, - void*, - float); + intptr_t( + VST_CALL_CONV* dispatcher)(AEffect*, int, int, intptr_t, void*, float); // process, quite sure 08-0b - void(VST_CALL_CONV* process)(AEffect*, float**, float**, int32_t); + void(VST_CALL_CONV* process)(AEffect*, float**, float**, int); // setParameter 0c-0f - void(VST_CALL_CONV* setParameter)(AEffect*, int32_t, float); + void(VST_CALL_CONV* setParameter)(AEffect*, int, float); // getParameter 10-13 - float(VST_CALL_CONV* getParameter)(AEffect*, int32_t); + float(VST_CALL_CONV* getParameter)(AEffect*, int); // programs 14-17 - int32_t numPrograms; + int numPrograms; // Params 18-1b - int32_t numParams; + int numParams; // Input 1c-1f - int32_t numInputs; + int numInputs; // Output 20-23 - int32_t numOutputs; + int numOutputs; // flags 24-27 - int32_t flags; + int flags; // Fill somewhere 28-2b void* ptr1; void* ptr2; - // Zeroes 2c-2f 30-33 34-37 38-3b - char empty3[4 + 4 + 4]; + int initialDelay; + // Zeroes 34-37 38-3b + int empty3a; + int empty3b; // 1.0f 3c-3f - float unknown_float; + float unkown_float; // An object? pointer 40-43 void* ptr3; // Zeroes 44-47 void* user; // Id 48-4b - int32_t uniqueID; - // Don't know 4c-4f - char unknown1[4]; + int uniqueID; + int version; // processReplacing 50-53 void(VST_CALL_CONV* processReplacing)(AEffect*, float**, float**, int); }; @@ -239,35 +305,78 @@ class VstTimeInfo { double samplePos; // 08 double sampleRate; - // unconfirmed 10 + // 10 double nanoSeconds; // 18 double ppqPos; - // 20 + // 20? double tempo; // 28 double barStartPos; - // 30 + // 30? double cycleStartPos; - // 38 + // 38? double cycleEndPos; - // 40 - int32_t timeSigNumerator; - // 44 - int32_t timeSigDenominator; - // 48 unused - int32_t smpteOffset; - // 4c unused - int32_t smpteFrameRate; - // 50? unused, where does this come from? - int32_t samplesToNextClock; + // 40? + int timeSigNumerator; + // 44? + int timeSigDenominator; + // unconfirmed 48 4c 50 + char empty3[4 + 4 + 4]; // 54 - int32_t flags; + int flags; }; typedef intptr_t(VST_CALL_CONV* audioMasterCallback)(AEffect*, - int32_t, - int32_t, + int, + int, intptr_t, void*, float); + +// from http://www.asseca.org/vst-24-specs/efGetParameterProperties.html +enum VstParameterFlags { + kVstParameterIsSwitch = 1 << 0, // parameter is a switch (on/off) + kVstParameterUsesIntegerMinMax = 1 << 1, // minInteger, maxInteger valid + kVstParameterUsesFloatStep = + 1 << 2, // stepFloat, smallStepFloat, largeStepFloat valid + kVstParameterUsesIntStep = 1 << 3, // stepInteger, largeStepInteger valid + kVstParameterSupportsDisplayIndex = 1 << 4, // displayIndex valid + kVstParameterSupportsDisplayCategory = 1 << 5, // category, etc. valid + kVstParameterCanRamp = 1 << 6 // set if parameter value can ramp up/down +}; + +// from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html +struct VstPatchChunkInfo { + int version; // Format Version (should be 1) + int pluginUniqueID; // UniqueID of the plug-in + int pluginVersion; // Plug-in Version + int numElements; // Number of Programs (Bank) or Parameters (Program) + char future[48]; // Reserved for future use +}; + +// from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html +enum VstPlugCategory { + kPlugCategUnknown = 0, // 0=Unknown, category not implemented + kPlugCategEffect, // 1=Simple Effect + kPlugCategSynth, // 2=VST Instrument (Synths, samplers,...) + kPlugCategAnalysis, // 3=Scope, Tuner, ... + kPlugCategMastering, // 4=Dynamics, ... + kPlugCategSpacializer, // 5=Panners, ... + kPlugCategRoomFx, // 6=Delays and Reverbs + kPlugSurroundFx, // 7=Dedicated surround processor + kPlugCategRestoration, // 8=Denoiser, ... + kPlugCategOfflineProcess, // 9=Offline Process + kPlugCategShell, // 10=Plug-in is container of other plug-ins @see + // effShellGetNextPlugin() + kPlugCategGenerator, // 11=ToneGenerator, ... + kPlugCategMaxCount // 12=Marker to count the categories +}; + +class VstRect { + public: + short top; + short left; + short bottom; + short right; +}; diff --git a/src/plugin/host-bridge.cpp b/src/plugin/host-bridge.cpp index 84f53248..c6efec31 100644 --- a/src/plugin/host-bridge.cpp +++ b/src/plugin/host-bridge.cpp @@ -52,11 +52,11 @@ std::optional find_wineprefix(); fs::path generate_endpoint_name(); bp::environment set_wineprefix(); -intptr_t dispatch_proxy(AEffect*, int32_t, int32_t, intptr_t, void*, float); -void process_proxy(AEffect*, float**, float**, int32_t); +intptr_t dispatch_proxy(AEffect*, int, int, intptr_t, void*, float); +void process_proxy(AEffect*, float**, float**, int); void process_replacing_proxy(AEffect*, float**, float**, int); -void setParameter_proxy(AEffect*, int32_t, float); -float getParameter_proxy(AEffect*, int32_t); +void setParameter_proxy(AEffect*, int, float); +float getParameter_proxy(AEffect*, int); /** * Fetch the bridge instance stored in an unused pointer from a VST plugin. This @@ -143,8 +143,8 @@ HostBridge::HostBridge(audioMasterCallback host_callback) * through to the winelib VST host. */ intptr_t HostBridge::dispatch(AEffect* /*plugin*/, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option) { @@ -200,7 +200,7 @@ void HostBridge::process_replacing(AEffect* /*plugin*/, } } -float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t index) { +float HostBridge::get_parameter(AEffect* /*plugin*/, int index) { logger.log_get_parameter(index); const Parameter request{index, std::nullopt}; @@ -212,9 +212,7 @@ float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t index) { return response.value.value(); } -void HostBridge::set_parameter(AEffect* /*plugin*/, - int32_t index, - float value) { +void HostBridge::set_parameter(AEffect* /*plugin*/, int index, float value) { logger.log_set_parameter(index, value); const Parameter request{index, value}; @@ -395,8 +393,8 @@ bp::environment set_wineprefix() { // `Bridge.cpp` intptr_t dispatch_proxy(AEffect* plugin, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option) { @@ -407,7 +405,7 @@ intptr_t dispatch_proxy(AEffect* plugin, void process_proxy(AEffect* plugin, float** inputs, float** outputs, - int32_t sample_frames) { + int sample_frames) { return get_bridge_instance(*plugin).process_replacing( plugin, inputs, outputs, sample_frames); } @@ -420,10 +418,10 @@ void process_replacing_proxy(AEffect* plugin, plugin, inputs, outputs, sample_frames); } -void setParameter_proxy(AEffect* plugin, int32_t index, float value) { +void setParameter_proxy(AEffect* plugin, int index, float value) { return get_bridge_instance(*plugin).set_parameter(plugin, index, value); } -float getParameter_proxy(AEffect* plugin, int32_t index) { +float getParameter_proxy(AEffect* plugin, int index) { return get_bridge_instance(*plugin).get_parameter(plugin, index); } diff --git a/src/plugin/host-bridge.h b/src/plugin/host-bridge.h index c7acd0ab..cf8dc994 100644 --- a/src/plugin/host-bridge.h +++ b/src/plugin/host-bridge.h @@ -55,8 +55,8 @@ class HostBridge { * passed through to the winelib VST host. */ intptr_t dispatch(AEffect* plugin, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option); @@ -68,8 +68,8 @@ class HostBridge { float** inputs, float** outputs, int sample_frames); - float get_parameter(AEffect* plugin, int32_t index); - void set_parameter(AEffect* plugin, int32_t index, float value); + float get_parameter(AEffect* plugin, int index); + void set_parameter(AEffect* plugin, int index, float value); /** * The path to `yabridge-host.exe`. diff --git a/src/wine-host/plugin-bridge.cpp b/src/wine-host/plugin-bridge.cpp index 35ff98fb..56a4fffc 100644 --- a/src/wine-host/plugin-bridge.cpp +++ b/src/wine-host/plugin-bridge.cpp @@ -32,7 +32,7 @@ using VstEntryPoint = AEffect*(VST_CALL_CONV*)(audioMasterCallback); PluginBridge* current_bridge_isntance = nullptr; intptr_t VST_CALL_CONV -host_callback_proxy(AEffect*, int32_t, int32_t, intptr_t, void*, float); +host_callback_proxy(AEffect*, int, int, intptr_t, void*, float); /** * Fetch the Pluginbridge instance stored in one of the two pointers reserved @@ -191,8 +191,8 @@ void PluginBridge::wait() { } intptr_t PluginBridge::host_callback(AEffect* /*plugin*/, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option) { @@ -201,8 +201,8 @@ intptr_t PluginBridge::host_callback(AEffect* /*plugin*/, } intptr_t VST_CALL_CONV host_callback_proxy(AEffect* effect, - int32_t opcode, - int32_t index, + int opcode, + int index, intptr_t value, void* data, float option) { diff --git a/src/wine-host/plugin-bridge.h b/src/wine-host/plugin-bridge.h index 919ce7e4..0ced2932 100644 --- a/src/wine-host/plugin-bridge.h +++ b/src/wine-host/plugin-bridge.h @@ -59,7 +59,7 @@ class PluginBridge { */ void wait(); - intptr_t host_callback(AEffect*, int32_t, int32_t, intptr_t, void*, float); + intptr_t host_callback(AEffect*, int, int, intptr_t, void*, float); private: /**