diff --git a/premake5.lua b/premake5.lua index 1a3dbaf64de..020770bd49f 100644 --- a/premake5.lua +++ b/premake5.lua @@ -133,6 +133,9 @@ elseif (os.istarget("windows")) then filter "platforms:x86" targetsuffix "_x86" + defines { + "WIN_X86=1" + } filter "platforms:x64" targetsuffix "" filter {} diff --git a/scripts/win/build-win.ps1 b/scripts/win/build-win.ps1 index d900c1b104b..4570430c46a 100644 --- a/scripts/win/build-win.ps1 +++ b/scripts/win/build-win.ps1 @@ -88,7 +88,7 @@ function Install-Surge New-Item -ItemType Directory -Force -Path $vst2Dir } Copy-Item "target\vst2\Release\Surge.dll" -Destination $vst2Dir -Force - Copy-Item "target\vst2\Release\Surge32.dll" -Destination $vst2Dir -Force + Copy-Item "target\vst2\Release\Surge_x86.dll" -Destination $vst2Dir -Force Write-Host "Start-Process -Verb runAs -WorkingDirectory $PSScriptRoot powershell -argumentlist install-vst3.ps1" Start-Process -Verb runAs "powershell" -argumentlist "$PSScriptRoot\install-vst3.ps1" diff --git a/scripts/win/install-vst3.ps1 b/scripts/win/install-vst3.ps1 index bdc119426ce..59ba4082827 100644 --- a/scripts/win/install-vst3.ps1 +++ b/scripts/win/install-vst3.ps1 @@ -7,4 +7,4 @@ If(!(Test-Path $vstDir)) } Copy-Item "$PSScriptRoot\..\..\target\vst3\Release\Surge.vst3" -Destination $vstDir -Force -Copy-Item "$PSScriptRoot\..\..\target\vst3\Release\Surge32.vst3" -Destination $vstDir -Force +Copy-Item "$PSScriptRoot\..\..\target\vst3\Release\Surge_x86.vst3" -Destination $vstDir -Force diff --git a/src/common/SurgeSynthesizer.cpp b/src/common/SurgeSynthesizer.cpp index 200e5b0ca82..77a2e93ba9d 100644 --- a/src/common/SurgeSynthesizer.cpp +++ b/src/common/SurgeSynthesizer.cpp @@ -1913,7 +1913,8 @@ void SurgeSynthesizer::getParameterNameW(long index, wchar_t* ptr) { if ((index >= 0) && (index < storage.getPatch().param_ptr.size())) { - swprintf(ptr, 128, L"%S", storage.getPatch().param_ptr[index]->get_full_name()); + // the input is not wide so don't use %S + swprintf(ptr, 128, L"%s", storage.getPatch().param_ptr[index]->get_full_name()); } else if (index >= metaparam_offset) { @@ -1924,7 +1925,7 @@ void SurgeSynthesizer::getParameterNameW(long index, wchar_t* ptr) } else { - swprintf(ptr, 128, L"C%i:%S", c + 1, storage.getPatch().CustomControllerLabel[c]); + swprintf(ptr, 128, L"C%i:%s", c + 1, storage.getPatch().CustomControllerLabel[c]); } } else @@ -1937,7 +1938,7 @@ void SurgeSynthesizer::getParameterShortNameW(long index, wchar_t* ptr) { if ((index >= 0) && (index < storage.getPatch().param_ptr.size())) { - swprintf(ptr, 128, L"%S", storage.getPatch().param_ptr[index]->get_name()); + swprintf(ptr, 128, L"%s", storage.getPatch().param_ptr[index]->get_name()); } else if (index >= metaparam_offset) { @@ -1948,7 +1949,7 @@ void SurgeSynthesizer::getParameterShortNameW(long index, wchar_t* ptr) } else { - swprintf(ptr, 128, L"C%i:%S", c + 1, storage.getPatch().CustomControllerLabel[c]); + swprintf(ptr, 128, L"C%i:%s", c + 1, storage.getPatch().CustomControllerLabel[c]); } } else @@ -1976,7 +1977,7 @@ void SurgeSynthesizer::getParameterStringW(long index, float value, wchar_t* ptr char text[128]; storage.getPatch().param_ptr[index]->get_display(text); - swprintf(ptr, 128, L"%S", text); + swprintf(ptr, 128, L"%s", text); } else if (index >= metaparam_offset) { diff --git a/src/common/gui/SurgeGUIEditor.cpp b/src/common/gui/SurgeGUIEditor.cpp index 8d4660e21f8..1ce807dd246 100644 --- a/src/common/gui/SurgeGUIEditor.cpp +++ b/src/common/gui/SurgeGUIEditor.cpp @@ -40,7 +40,6 @@ const int yofs = 10; using namespace VSTGUI; using namespace std; - CFontRef displayFont = NULL; CFontRef patchNameFont = NULL; CFontRef lfoTypeFont = NULL; @@ -2450,6 +2449,11 @@ long SurgeGUIEditor::applyParameterOffset(long id) return id-start_paramtags; } +long SurgeGUIEditor::unapplyParameterOffset(long id) +{ + return id + start_paramtags; +} + void SurgeGUIEditor::setZoomFactor(int zf) { if (zf < minimumZoom) diff --git a/src/common/gui/SurgeGUIEditor.h b/src/common/gui/SurgeGUIEditor.h index f87c2736c3f..ff700192742 100644 --- a/src/common/gui/SurgeGUIEditor.h +++ b/src/common/gui/SurgeGUIEditor.h @@ -49,8 +49,9 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi virtual void beginEdit(long index); virtual void endEdit(long index); - virtual long applyParameterOffset(long index); - + static long applyParameterOffset(long index); + static long unapplyParameterOffset(long index); + #if !TARGET_VST3 bool open(void* parent) override; void close() override; diff --git a/src/vst2/Vst2PluginInstance.cpp b/src/vst2/Vst2PluginInstance.cpp index 4d514141a59..b56f9295d79 100644 --- a/src/vst2/Vst2PluginInstance.cpp +++ b/src/vst2/Vst2PluginInstance.cpp @@ -530,12 +530,14 @@ VstInt32 Vst2PluginInstance::setChunk(void* data, VstInt32 byteSize, bool isPres bool Vst2PluginInstance::beginEdit( VstInt32 index ) { - return AudioEffectX::beginEdit( ((SurgeGUIEditor *)editor)->applyParameterOffset( _instance->remapExternalApiToInternalId(index ) ) ); + return AudioEffectX::beginEdit( + SurgeGUIEditor::applyParameterOffset(_instance->remapExternalApiToInternalId(index))); } bool Vst2PluginInstance::endEdit( VstInt32 index ) { - return AudioEffectX::endEdit( ((SurgeGUIEditor *)editor)->applyParameterOffset( _instance->remapExternalApiToInternalId(index))); + return AudioEffectX::endEdit( + SurgeGUIEditor::applyParameterOffset(_instance->remapExternalApiToInternalId(index))); } bool Vst2PluginInstance::tryInit() diff --git a/src/vst3/SurgeVst3Processor.cpp b/src/vst3/SurgeVst3Processor.cpp index 900f838ecbc..37317cd2260 100644 --- a/src/vst3/SurgeVst3Processor.cpp +++ b/src/vst3/SurgeVst3Processor.cpp @@ -13,6 +13,12 @@ #include "CScalableBitmap.h" #include +#include +#include +#include + +#define MIDI_CONTROLLER_0 20000 +#define MIDI_CONTROLLER_MAX 24096 using namespace Steinberg::Vst; @@ -52,7 +58,7 @@ tresult PLUGIN_API SurgeVst3Processor::initialize(FUnknown* context) addAudioOutput(STR16("Stereo Out"), SpeakerArr::kStereo); //---create Event In/Out busses (1 bus with 16 channels)------ - addEventInput(STR16("Note In")); + addEventInput(USTRING("MIDI In")); // addUnit(new Unit(USTRING ("Macro Parameters"), 1)); @@ -232,47 +238,68 @@ void SurgeVst3Processor::processParameterChanges(int sampleOffset, if (paramQueue) { int32 offsetSamples; - double value; + double value = 0; + ; int32 numPoints = paramQueue->getPointCount(); - /*switch (paramQueue->getParameterId ()) - { - }*/ + int id = paramQueue->getParameterId(); + + if (id >= MIDI_CONTROLLER_0 && id <= MIDI_CONTROLLER_MAX) + { + int chancont = id - MIDI_CONTROLLER_0; + int channel = chancont & 0xF; + int cont = chancont >> 4; + + for (int i = 0; i < numPoints; ++i) + { + paramQueue->getPoint(0, offsetSamples, value); + if (cont < 128) + { + if (cont == ControllerNumbers::kCtrlAllSoundsOff || + cont == ControllerNumbers::kCtrlAllNotesOff) + { + surgeInstance->allNotesOff(); + } + else + { + surgeInstance->channelController(channel, cont, (int)(value * 128)); + } + } + else + switch (cont) + { + case kAfterTouch: + surgeInstance->channelAftertouch(channel, (int)(value * 127.f)); + break; + case kPitchBend: + surgeInstance->pitchBend(channel, (int)(value * 8192.f)); + break; + case kCtrlProgramChange: + break; + case kCtrlPolyPressure: + break; + default: + break; + } + } + } + else + { + int id = paramQueue->getParameterId(); + + if (numPoints == 1) + { + paramQueue->getPoint(0, offsetSamples, value); + surgeInstance->setParameter01(id, value, true); + } + else + { + // Unclear what to do here + } + } } } } - /*int32 numParamsChanged = paramChanges->getParameterCount (); - // for each parameter which are some changes in this audio block: - for (int32 i = 0; i < numParamsChanged; i++) - { - IParamValueQueue* paramQueue = paramChanges->getParameterData (i); - if (paramQueue) - { - int32 offsetSamples; - double value; - int32 numPoints = paramQueue->getPointCount (); - switch (paramQueue->getParameterId ()) - { - case kGainId: - // we use in this example only the last point of the queue. - // in some wanted case for specific kind of parameter it makes sense to retrieve all - points - // and process the whole audio block in small blocks. - if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue) - { - fGain = (float)value; - } - break; - - case kBypassId: - if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue) - { - bBypass = (value > 0.5f); - } - break; - } - } - }*/ } tresult PLUGIN_API SurgeVst3Processor::process(ProcessData& data) @@ -414,6 +441,27 @@ IPlugView* PLUGIN_API SurgeVst3Processor::createView(const char* name) return nullptr; } +tresult SurgeVst3Processor::beginEdit(ParamID id) +{ + int mappedId = + SurgeGUIEditor::applyParameterOffset(surgeInstance->remapExternalApiToInternalId(id)); + return Steinberg::Vst::SingleComponentEffect::beginEdit(mappedId); +} + +tresult SurgeVst3Processor::performEdit(ParamID id, Steinberg::Vst::ParamValue valueNormalized) +{ + int mappedId = + SurgeGUIEditor::applyParameterOffset(surgeInstance->remapExternalApiToInternalId(id)); + return Steinberg::Vst::SingleComponentEffect::performEdit(mappedId, valueNormalized); +} + +tresult SurgeVst3Processor::endEdit(ParamID id) +{ + int mappedId = + SurgeGUIEditor::applyParameterOffset(surgeInstance->remapExternalApiToInternalId(id)); + return Steinberg::Vst::SingleComponentEffect::endEdit(mappedId); +} + void SurgeVst3Processor::editorAttached(EditorView* editor) { SurgeGUIEditor* view = dynamic_cast(editor); @@ -433,10 +481,14 @@ void SurgeVst3Processor::editorRemoved(EditorView* editor) } void SurgeVst3Processor::addDependentView(SurgeGUIEditor* view) -{} +{ + viewsSet.insert(view); +} void SurgeVst3Processor::removeDependentView(SurgeGUIEditor* view) -{} +{ + viewsSet.erase(view); +} int32 PLUGIN_API SurgeVst3Processor::getParameterCount() { @@ -474,9 +526,35 @@ tresult PLUGIN_API SurgeVst3Processor::getParameterInfo(int32 paramIndex, Parame info.id = id; - surgeInstance->getParameterNameW(id, reinterpret_cast(info.title)); - surgeInstance->getParameterShortNameW(id, reinterpret_cast(info.shortTitle)); - surgeInstance->getParameterUnitW(id, reinterpret_cast(info.units)); + /* + ** String128 is a TChar[128] is a char16[128]. On mac, wchar is a char32 so + ** the original reinrpret cast didn't work well. + ** + ** I thought a lot about using std::wstring_convert> here + ** but in the end decided to just copy the bytes + */ + wchar_t tmpwchar[512]; + surgeInstance->getParameterNameW(id, tmpwchar); +#if MAC + std::copy(tmpwchar, tmpwchar + 128, info.title); +#else + swprintf(reinterpret_cast(info.title), 128, L"%S", tmpwchar); +#endif + + surgeInstance->getParameterShortNameW(id, tmpwchar); +#if MAC + std::copy(tmpwchar, tmpwchar + 128, info.shortTitle); +#else + swprintf(reinterpret_cast(info.shortTitle), 128, L"%S", tmpwchar); +#endif + + surgeInstance->getParameterUnitW(id, tmpwchar); +#if MAC + std::copy(tmpwchar, tmpwchar + 128, info.units); +#else + swprintf(reinterpret_cast(info.units), 128, L"%S", tmpwchar); +#endif + info.stepCount = 0; // 1 = toggle, info.defaultNormalizedValue = meta.fdefault; info.unitId = 0; // meta.clump; @@ -496,7 +574,14 @@ tresult PLUGIN_API SurgeVst3Processor::getParamStringByValue(ParamID tag, return kInvalidArgument; } - surgeInstance->getParameterStringW(tag, valueNormalized, reinterpret_cast(string)); + + wchar_t tmpwchar[ 512 ]; + surgeInstance->getParameterStringW(tag, valueNormalized, tmpwchar); +#if MAC + std::copy(string, string+128, tmpwchar); +#else + swprintf(reinterpret_cast(string), 128, L"%S", tmpwchar); +#endif return kResultOk; } @@ -578,7 +663,14 @@ tresult PLUGIN_API SurgeVst3Processor::getMidiControllerAssignment(int32 busInde CtrlNumber midiControllerNumber, ParamID& id /*out*/) { - return kResultFalse; + /* + ** Alrighty dighty. What VST3 wants us to do here is, for the controller number, + ** tell it a parameter to map to. We alas don't have a parameter to map to because + ** that's not how surge works. But... we can map to parameter id of MIDI_CONTROLLER_0 + id + ** and test that elsewhere + */ + id = MIDI_CONTROLLER_0 + midiControllerNumber * 16 + channel; + return kResultTrue; } bool SurgeVst3Processor::exportAllMidiControllers() @@ -602,9 +694,12 @@ void SurgeVst3Processor::updateDisplay() // setDirty(true); } -void SurgeVst3Processor::setParameterAutomated(int externalparam, float value) +void SurgeVst3Processor::setParameterAutomated(int inputParam, float value) { - beginEdit(externalparam); // TODO + int externalparam = SurgeGUIEditor::unapplyParameterOffset( + surgeInstance->remapExternalApiToInternalId(inputParam)); + + beginEdit(externalparam); performEdit(externalparam, value); endEdit(externalparam); } diff --git a/src/vst3/SurgeVst3Processor.h b/src/vst3/SurgeVst3Processor.h index 60433bca50c..ecc01afb7ac 100644 --- a/src/vst3/SurgeVst3Processor.h +++ b/src/vst3/SurgeVst3Processor.h @@ -5,6 +5,7 @@ #include "pluginterfaces/vst/ivstevents.h" #include #include +#include using namespace Steinberg; @@ -12,7 +13,8 @@ class SurgeGUIEditor; class SurgeSynthesizer; // we need public EditController, public IAudioProcessor -class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect //, public IMidiMapping +class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect, + public Steinberg::Vst::IMidiMapping { public: SurgeVst3Processor(); @@ -99,7 +101,7 @@ class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect //, publ getMidiControllerAssignment(int32 busIndex, int16 channel, Steinberg::Vst::CtrlNumber midiControllerNumber, - Steinberg::Vst::ParamID& id /*out*/); + Steinberg::Vst::ParamID& id /*out*/) override; //! when true, surge exports all normal 128 CC parameters, aftertouch and pitch bend as //! parameters (but not automatable) @@ -108,6 +110,20 @@ class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect //, publ void updateDisplay(); void setParameterAutomated(int externalparam, float value); +#if WIN_X86 + // For some undebuggable reason, 32 bit windows doesn't like hte PLUGIN_API + // 32 bit vst3 is worth 0 time debugging; this fix makes it work. + virtual tresult beginEdit(Steinberg::Vst::ParamID id); + virtual tresult performEdit(Steinberg::Vst::ParamID id, + Steinberg::Vst::ParamValue valueNormalized); + virtual tresult endEdit(Steinberg::Vst::ParamID id); +#else + virtual tresult PLUGIN_API beginEdit(Steinberg::Vst::ParamID id); + virtual tresult PLUGIN_API performEdit(Steinberg::Vst::ParamID id, + Steinberg::Vst::ParamValue valueNormalized); + virtual tresult PLUGIN_API endEdit(Steinberg::Vst::ParamID id); +#endif + protected: void createSurge(); void destroySurge(); @@ -118,10 +134,17 @@ class SurgeVst3Processor : public Steinberg::Vst::SingleComponentEffect //, publ int32 getParameterCountWithoutMappings(); std::unique_ptr surgeInstance; - std::vector viewsArray; + std::set viewsSet; int blockpos; void handleZoom(SurgeGUIEditor *e); FpuState _fpuState; + +public: + OBJ_METHODS(SurgeVst3Processor, Steinberg::Vst::SingleComponentEffect) + DEFINE_INTERFACES + DEF_INTERFACE(Steinberg::Vst::IMidiMapping) + END_DEFINE_INTERFACES(Steinberg::Vst::SingleComponentEffect) + REFCOUNT_METHODS(Steinberg::Vst::SingleComponentEffect) };