View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001401 | OpenMPT | Plugins / VST | public | 2020-12-22 17:04 | 2021-01-10 18:30 |
Reporter | manx | Assigned To | manx | ||
Priority | high | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | OpenMPT 1.30.00.* (old testing) | ||||
Target Version | OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) | Fixed in Version | OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) | ||
Summary | 0001401: Do not silently ignore crashes in VST plugins by default any more | ||||
Description | This had already been discussed before the 1.29 release. | ||||
Tags | No tags attached. | ||||
Has the bug occurred in previous versions? | |||||
Tested code revision (in case you know it) | |||||
vst-seh-v10.patch (24,641 bytes)
Index: mptrack/ModDocTemplate.cpp =================================================================== --- mptrack/ModDocTemplate.cpp (revision 13970) +++ mptrack/ModDocTemplate.cpp (working copy) @@ -130,7 +130,7 @@ if(const auto fileExt = filename.GetFileExt(); !mpt::PathString::CompareNoCase(fileExt, P_(".dll")) || !mpt::PathString::CompareNoCase(fileExt, P_(".vst3"))) { CVstPluginManager *pPluginManager = theApp.GetPluginManager(); - if(pPluginManager && pPluginManager->AddPlugin(filename) != nullptr) + if(pPluginManager && pPluginManager->AddPlugin(filename, TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes) != nullptr) { return nullptr; } Index: mptrack/Mptrack.cpp =================================================================== --- mptrack/Mptrack.cpp (revision 13970) +++ mptrack/Mptrack.cpp (working copy) @@ -1847,6 +1847,8 @@ m_pPluginManager = new CVstPluginManager; const size_t numPlugins = GetSettings().Read<int32>(U_("VST Plugins"), U_("NumPlugins"), 0); + bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes; + std::vector<VSTPluginLib *> nonFoundPlugs; const mpt::PathString failedPlugin = GetSettings().Read<mpt::PathString>(U_("VST Plugins"), U_("FailedPlugin"), P_("")); @@ -1911,7 +1913,7 @@ mpt::ustring plugTags = GetSettings().Read<mpt::ustring>(U_("VST Plugins"), tagFormat(plug), mpt::ustring()); bool plugFound = true; - VSTPluginLib *lib = m_pPluginManager->AddPlugin(plugPath, plugTags, true, &plugFound); + VSTPluginLib *lib = m_pPluginManager->AddPlugin(plugPath, maskCrashes, plugTags, true, &plugFound); if(!plugFound && lib != nullptr) { nonFoundPlugs.push_back(lib); Index: mptrack/SelectPluginDialog.cpp =================================================================== --- mptrack/SelectPluginDialog.cpp (revision 13970) +++ mptrack/SelectPluginDialog.cpp (working copy) @@ -658,7 +658,7 @@ for(const auto &file : dlg.GetFilenames()) { - VSTPluginLib *lib = plugManager->AddPlugin(file, mpt::ustring(), false); + VSTPluginLib *lib = plugManager->AddPlugin(file, TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes, mpt::ustring(), false); if(lib != nullptr) { update = true; @@ -715,6 +715,7 @@ pluginScanDlg.ShowWindow(SW_SHOW); FolderScanner scan(path, FolderScanner::kOnlyFiles | FolderScanner::kFindInSubDirectories); + bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes; mpt::PathString fileName; int files = 0; while(scan.Next(fileName) && pluginScanDlg.IsWindowVisible()) @@ -731,7 +732,7 @@ ::DispatchMessage(&msg); } - VSTPluginLib *lib = pManager->AddPlugin(fileName, mpt::ustring(), false); + VSTPluginLib *lib = pManager->AddPlugin(fileName, maskCrashes, mpt::ustring(), false); if(lib) { update = true; Index: mptrack/TrackerSettings.cpp =================================================================== --- mptrack/TrackerSettings.cpp (revision 13970) +++ mptrack/TrackerSettings.cpp (working copy) @@ -314,6 +314,8 @@ , vstHostProductString(conf, U_("VST Plugins"), U_("HostProductString"), "OpenMPT") , vstHostVendorString(conf, U_("VST Plugins"), U_("HostVendorString"), "OpenMPT project") , vstHostVendorVersion(conf, U_("VST Plugins"), U_("HostVendorVersion"), Version::Current().GetRawVersion()) + // Broken Plugins Workarounds + , BrokenPluginsWorkaroundVSTMaskAllCrashes(conf, U_("Broken Plugins Workarounds"), U_("VSTMaskAllCrashes"), true) // TODO: really should be false // Update , UpdateEnabled(conf, U_("Update"), U_("Enabled"), true) , UpdateInstallAutomatically(conf, U_("Update"), U_("InstallAutomatically"), false) Index: mptrack/TrackerSettings.h =================================================================== --- mptrack/TrackerSettings.h (revision 13970) +++ mptrack/TrackerSettings.h (working copy) @@ -850,6 +850,10 @@ CachedSetting<mpt::lstring> vstHostVendorString; CachedSetting<int32> vstHostVendorVersion; + // Broken Plugins Workarounds + + Setting<bool> BrokenPluginsWorkaroundVSTMaskAllCrashes; + // Update Setting<bool> UpdateEnabled; Index: mptrack/Vstplug.cpp =================================================================== --- mptrack/Vstplug.cpp (revision 13970) +++ mptrack/Vstplug.cpp (working copy) @@ -19,6 +19,7 @@ #include "AbstractVstEditor.h" #include "VSTEditor.h" #include "DefaultVstEditor.h" +#include "ExceptionHandler.h" #endif // MODPLUG_TRACKER #include "../soundlib/Sndfile.h" #include "../soundlib/MIDIEvents.h" @@ -29,6 +30,7 @@ #include "../pluginBridge/BridgeOpCodes.h" #include "../soundlib/plugins/OpCodes.h" #include "../soundlib/plugins/PluginManager.h" +#include "../common/mptOSException.h" using namespace Vst; DECLARE_FLAGSET(Vst::VstTimeInfoFlags) @@ -41,55 +43,58 @@ #define VST_LOG #endif -// Try loading the VST library. -static bool LoadLibrarySEH(const mpt::RawPathString &pluginPath, HMODULE &library) + +using VstCrash = Windows::SEH::Code; + + +bool CVstPlugin::MaskCrashes() noexcept { - __try - { - library = LoadLibrary(pluginPath.c_str()); - return true; - } __except(EXCEPTION_EXECUTE_HANDLER) - { - return false; - } + return m_maskCrashes; } -static AEffect *CallMainProc(Vst::MainProc pMainProc) +template <typename Tfn> +DWORD CVstPlugin::SETryOrError(bool maskCrashes, Tfn fn) { - __try + DWORD exception = 0; + if(maskCrashes) { - return pMainProc(CVstPlugin::MasterCallBack); - } __except(EXCEPTION_EXECUTE_HANDLER) + exception = Windows::SEH::TryOrError(fn); + if(exception) + { + ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin); + } + } else { - return nullptr; + fn(); } + return exception; } -// Try loading the VST plugin and retrieve the AEffect structure. -static AEffect *GetAEffectSEH(HMODULE library) +template <typename Tfn> +DWORD CVstPlugin::SETryOrError(Tfn fn) { - auto pMainProc = (Vst::MainProc)GetProcAddress(library, "VSTPluginMain"); - if(pMainProc == nullptr) + DWORD exception = 0; + if(MaskCrashes()) { - pMainProc = (Vst::MainProc)GetProcAddress(library, "main"); - } - - if(pMainProc != nullptr) - { - return CallMainProc(pMainProc); + exception = Windows::SEH::TryOrError(fn); + if(exception) + { + ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin); + } } else { -#ifdef VST_LOG - MPT_LOG(LogDebug, "VST", MPT_UFORMAT("Entry point not found! (handle={})")(mpt::ufmt::PTR(library))); -#endif // VST_LOG - return nullptr; +#ifdef MODPLUG_TRACKER + ExceptionHandler::ContextSetter ectxguard{&m_Ectx}; +#endif // MODPLUG_TRACKER + fn(); } + return exception; } -AEffect *CVstPlugin::LoadPlugin(VSTPluginLib &plugin, HMODULE &library, bool forceBridge) +AEffect *CVstPlugin::LoadPlugin(bool maskCrashes, VSTPluginLib &plugin, HMODULE &library, bool forceBridge) { const mpt::PathString &pluginPath = plugin.dllPath; @@ -137,9 +142,17 @@ plugin.useBridge = false; } - if(!LoadLibrarySEH(pluginPath.AsNative(), library)) { - CVstPluginManager::ReportPlugException(MPT_UFORMAT("Exception caught while loading {}")(pluginPath)); +#ifdef MODPLUG_TRACKER + ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) }; + ExceptionHandler::ContextSetter ectxguard{&ectx}; +#endif // MODPLUG_TRACKER + DWORD exception = SETryOrError(maskCrashes, [&](){ library = LoadLibrary(pluginPath.AsNative().c_str()); }); + if(exception) + { + CVstPluginManager::ReportPlugException(MPT_UFORMAT("Exception caught while loading {}")(pluginPath)); + return nullptr; + } } if(library == nullptr) { @@ -167,7 +180,30 @@ if(library != nullptr && library != INVALID_HANDLE_VALUE) { - effect = GetAEffectSEH(library); + auto pMainProc = (Vst::MainProc)GetProcAddress(library, "VSTPluginMain"); + if(pMainProc == nullptr) + { + pMainProc = (Vst::MainProc)GetProcAddress(library, "main"); + } + + if(pMainProc != nullptr) + { +#ifdef MODPLUG_TRACKER + ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) }; + ExceptionHandler::ContextSetter ectxguard{&ectx}; +#endif // MODPLUG_TRACKER + DWORD exception = SETryOrError(maskCrashes, [&](){ effect = pMainProc(CVstPlugin::MasterCallBack); }); + if(exception) + { + return nullptr; + } + } else + { +#ifdef VST_LOG + MPT_LOG(LogDebug, "VST", MPT_UFORMAT("Entry point not found! (handle={})")(mpt::ufmt::PTR(library))); +#endif // VST_LOG + return nullptr; + } } return effect; @@ -809,8 +845,9 @@ // CVstPlugin // -CVstPlugin::CVstPlugin(HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixStruct, AEffect &effect, CSoundFile &sndFile) +CVstPlugin::CVstPlugin(bool maskCrashes, HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixStruct, AEffect &effect, CSoundFile &sndFile) : IMidiPlugin(factory, sndFile, &mixStruct) + , m_maskCrashes(maskCrashes) , m_Effect(effect) , timeInfo{} , isBridged(!memcmp(&effect.reservedForHost2, "OMPT", 4)) @@ -829,6 +866,9 @@ void CVstPlugin::Initialize() { + + m_Ectx = { MPT_UFORMAT("VST Plugin: {}")(m_Factory.dllPath.ToUnicode()) }; + // If filename matched during load but plugin ID didn't, make sure it's updated. m_pMixStruct->Info.dwPluginId1 = m_Factory.pluginId1 = m_Effect.magic; m_pMixStruct->Info.dwPluginId2 = m_Factory.pluginId2 = m_Effect.uniqueID; @@ -1020,16 +1060,17 @@ // Wrapper for VST dispatch call with structured exception handling. -intptr_t CVstPlugin::DispatchSEH(AEffect *effect, VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception) +intptr_t CVstPlugin::DispatchSEH(bool maskCrashes, AEffect *effect, VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception) { - __try + if(effect->dispatcher != nullptr) { - if(effect->dispatcher != nullptr) + intptr_t result = 0; + DWORD e = SETryOrError(maskCrashes, [&](){ result = effect->dispatcher(effect, opCode, index, value, ptr, opt); }); + if(e) { - return effect->dispatcher(effect, opCode, index, value, ptr, opt); + exception = e; } - } __except((exception = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) - { + return result; } return 0; } @@ -1037,29 +1078,39 @@ intptr_t CVstPlugin::Dispatch(VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt) { - unsigned long exception = 0; #ifdef VST_LOG { mpt::ustring codeStr; if(opCode < std::size(VstOpCodes)) + { codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]); - else + } else + { codeStr = mpt::ufmt::val(opCode); + } MPT_LOG(LogDebug, "VST", MPT_UFORMAT("About to Dispatch({}) (Plugin=\"{}\"), index: {}, value: {}, ptr: {}, opt: {}!\n")(codeStr, m_Factory.libraryName, index, mpt::ufmt::PTR(value), mpt::ufmt::PTR(ptr), mpt::ufmt::flt(opt, 3))); } #endif - intptr_t result = DispatchSEH(&m_Effect, opCode, index, value, ptr, opt, exception); - - if(exception) + if(!m_Effect.dispatcher) { - mpt::ustring codeStr; - if(opCode < static_cast<int32>(std::size(VstOpCodes))) - codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]); - else - codeStr = mpt::ufmt::val(opCode); - ReportPlugException(MPT_UFORMAT("Exception {} in Dispatch({})")(mpt::ufmt::HEX0<8>(exception), codeStr)); + return 0; } - + intptr_t result = 0; + { + DWORD exception = SETryOrError([&](){ result = m_Effect.dispatcher(&m_Effect, opCode, index, value, ptr, opt); }); + if(exception) + { + mpt::ustring codeStr; + if(opCode < std::size(VstOpCodes)) + { + codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]); + } else + { + codeStr = mpt::ufmt::val(opCode); + } + ReportPlugException(MPT_UFORMAT("Exception {} in Dispatch({})")(mpt::ufmt::HEX0<8>(exception), codeStr)); + } + } return result; } @@ -1163,11 +1214,9 @@ float fResult = 0; if(nIndex < m_Effect.numParams && m_Effect.getParameter != nullptr) { - __try + DWORD exception = SETryOrError([&](){ fResult = m_Effect.getParameter(&m_Effect, nIndex); }); + if(exception) { - fResult = m_Effect.getParameter(&m_Effect, nIndex); - } __except(EXCEPTION_EXECUTE_HANDLER) - { //ReportPlugException(U_("Exception in getParameter (Plugin=\"{}\")!\n"), m_Factory.szLibraryName); } } @@ -1177,16 +1226,15 @@ void CVstPlugin::SetParameter(PlugParamIndex nIndex, PlugParamValue fValue) { - __try + DWORD exception = 0; + if(nIndex < m_Effect.numParams && m_Effect.setParameter) { - if(nIndex < m_Effect.numParams && m_Effect.setParameter) - { - m_Effect.setParameter(&m_Effect, nIndex, fValue); - } - ResetSilence(); - } __except(EXCEPTION_EXECUTE_HANDLER) + exception = SETryOrError([&](){ m_Effect.setParameter(&m_Effect, nIndex, fValue); }); + } + ResetSilence(); + if(exception) { - //ReportPlugException(MPT_UFORMAT("Exception in SetParameter({}, {})!")(nIndex, fValue)); + //ReportPlugException(mpt::format(U_("Exception in SetParameter({}, {})!"))(nIndex, fValue)); } } @@ -1273,8 +1321,7 @@ // Process VST events if(m_Effect.dispatcher != nullptr && vstEvents.Finalise() > 0) { - unsigned long exception = 0; - DispatchSEH(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0, exception); + DWORD exception = SETryOrError([&](){ m_Effect.dispatcher(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0); }); ResetSilence(); if(exception) { @@ -1342,18 +1389,6 @@ } -// Wrapper for VST process call with structured exception handling. -static void ProcessSEH(Vst::ProcessProc processFP, AEffect* effect, float** inputs, float** outputs, int32 sampleFrames, unsigned long &exception) -{ - __try - { - processFP(effect, inputs, outputs, sampleFrames); - } __except((exception = GetExceptionCode()), EXCEPTION_EXECUTE_HANDLER) - { - } -} - - void CVstPlugin::Process(float *pOutL, float *pOutR, uint32 numFrames) { ProcessVSTEvents(); @@ -1382,14 +1417,15 @@ } // Do the VST processing magic - ASSERT(numFrames <= MIXBUFFERSIZE); - unsigned long exception = 0; - ProcessSEH(m_pProcessFP, &m_Effect, m_mixBuffer.GetInputBufferArray(), outputBuffers, numFrames, exception); - if(exception) + MPT_ASSERT(numFrames <= MIXBUFFERSIZE); { - Bypass(); - mpt::ustring processMethod = (m_Effect.flags & effFlagsCanReplacing) ? U_("processReplacing") : U_("process"); - ReportPlugException(MPT_UFORMAT("The plugin threw an exception ({}) in {}. It has automatically been set to \"Bypass\".")(mpt::ufmt::HEX0<8>(exception), processMethod)); + DWORD exception = SETryOrError([&](){ m_pProcessFP(&m_Effect, m_mixBuffer.GetInputBufferArray(), outputBuffers, numFrames); }); + if(exception) + { + Bypass(); + mpt::ustring processMethod = (m_Effect.flags & effFlagsCanReplacing) ? U_("processReplacing") : U_("process"); + ReportPlugException(MPT_UFORMAT("The plugin threw an exception ({}) in {}. It has automatically been set to \"Bypass\".")(mpt::ufmt::HEX0<8>(exception), processMethod)); + } } // Mix outputs of multi-output VSTs: Index: mptrack/Vstplug.h =================================================================== --- mptrack/Vstplug.h (revision 13970) +++ mptrack/Vstplug.h (working copy) @@ -19,7 +19,11 @@ #include "../soundlib/Mixer.h" #include "plugins/VstDefinitions.h" #include "plugins/VstEventQueue.h" +#if defined(MODPLUG_TRACKER) +#include "ExceptionHandler.h" +#endif // MODPLUG_TRACKER + OPENMPT_NAMESPACE_BEGIN @@ -31,6 +35,8 @@ class CVstPlugin final : public IMidiPlugin { protected: + + bool m_maskCrashes; HMODULE m_hLibrary; Vst::AEffect &m_Effect; Vst::ProcessProc m_pProcessFP = nullptr; // Function pointer to AEffect processReplacing if supported, else process. @@ -49,13 +55,29 @@ Vst::VstTimeInfo timeInfo; public: + const bool isBridged : 1; // True if our built-in plugin bridge is being used. +private: + +#if defined(MODPLUG_TRACKER) + ExceptionHandler::Context m_Ectx; +#endif // MODPLUG_TRACKER + public: - CVstPlugin(HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixPlugin, Vst::AEffect &effect, CSoundFile &sndFile); + bool MaskCrashes() noexcept; + +public: + template <typename Tfn> static DWORD SETryOrError(bool maskCrashes, Tfn fn); + +private: + template <typename Tfn> DWORD SETryOrError(Tfn fn); + +public: + CVstPlugin(bool maskCrashes, HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixPlugin, Vst::AEffect &effect, CSoundFile &sndFile); ~CVstPlugin(); - static Vst::AEffect *LoadPlugin(VSTPluginLib &plugin, HMODULE &library, bool forceBridge); + static Vst::AEffect *LoadPlugin(bool maskCrashes, VSTPluginLib &plugin, HMODULE &library, bool forceBridge); protected: void Initialize(); @@ -91,7 +113,7 @@ CString GetParamLabel(PlugParamIndex param) override { return GetParamPropertyString(param, Vst::effGetParamLabel); }; CString GetParamDisplay(PlugParamIndex param) override { return GetParamPropertyString(param, Vst::effGetParamDisplay); }; - static intptr_t DispatchSEH(Vst::AEffect *effect, Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception); + static intptr_t DispatchSEH(bool maskCrashes, Vst::AEffect *effect, Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception); intptr_t Dispatch(Vst::VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt); bool HasEditor() const override { return (m_Effect.flags & Vst::effFlagsHasEditor) != 0; } Index: soundlib/plugins/PluginManager.cpp =================================================================== --- soundlib/plugins/PluginManager.cpp (revision 13970) +++ soundlib/plugins/PluginManager.cpp (working copy) @@ -55,6 +55,7 @@ #include "../../mptrack/TrackerSettings.h" #include "../../mptrack/AbstractVstEditor.h" #include "../../soundlib/AudioCriticalSection.h" +#include "../mptrack/ExceptionHandler.h" #include "../common/mptCRC.h" #endif // MODPLUG_TRACKER @@ -427,10 +428,10 @@ // Extract instrument and category information from plugin. #ifndef NO_VST -static void GetPluginInformation(Vst::AEffect *effect, VSTPluginLib &library) +static void GetPluginInformation(bool maskCrashes, Vst::AEffect *effect, VSTPluginLib &library) { unsigned long exception = 0; - library.category = static_cast<VSTPluginLib::PluginCategory>(CVstPlugin::DispatchSEH(effect, Vst::effGetPlugCategory, 0, 0, nullptr, 0, exception)); + library.category = static_cast<VSTPluginLib::PluginCategory>(CVstPlugin::DispatchSEH(maskCrashes, effect, Vst::effGetPlugCategory, 0, 0, nullptr, 0, exception)); library.isInstrument = ((effect->flags & Vst::effFlagsIsSynth) || !effect->numInputs); if(library.isInstrument) @@ -443,7 +444,7 @@ #ifdef MODPLUG_TRACKER std::vector<char> s(256, 0); - CVstPlugin::DispatchSEH(effect, Vst::effGetVendorString, 0, 0, s.data(), 0, exception); + CVstPlugin::DispatchSEH(maskCrashes, effect, Vst::effGetVendorString, 0, 0, s.data(), 0, exception); library.vendor = mpt::ToCString(mpt::Charset::Locale, s.data()); #endif // MODPLUG_TRACKER } @@ -452,7 +453,7 @@ #ifdef MODPLUG_TRACKER // Add a plugin to the list of known plugins. -VSTPluginLib *CVstPluginManager::AddPlugin(const mpt::PathString &dllPath, const mpt::ustring &tags, bool fromCache, bool *fileFound) +VSTPluginLib *CVstPluginManager::AddPlugin(const mpt::PathString &dllPath, bool maskCrashes, const mpt::ustring &tags, bool fromCache, bool *fileFound) { const mpt::PathString fileName = dllPath.GetFileName(); @@ -535,32 +536,39 @@ unsigned long exception = 0; // Always scan plugins in a separate process HINSTANCE hLib = NULL; - Vst::AEffect *pEffect = CVstPlugin::LoadPlugin(*plug, hLib, true); - - if(pEffect != nullptr && pEffect->magic == Vst::kEffectMagic && pEffect->dispatcher != nullptr) { - CVstPlugin::DispatchSEH(pEffect, Vst::effOpen, 0, 0, 0, 0, exception); +#ifdef MODPLUG_TRACKER + ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plug->dllPath.ToUnicode()) }; + ExceptionHandler::ContextSetter ectxguard{&ectx}; +#endif // MODPLUG_TRACKER - plug->pluginId1 = pEffect->magic; - plug->pluginId2 = pEffect->uniqueID; + Vst::AEffect *pEffect = CVstPlugin::LoadPlugin(maskCrashes, *plug, hLib, true); - GetPluginInformation(pEffect, *plug); + if(pEffect != nullptr && pEffect->magic == Vst::kEffectMagic && pEffect->dispatcher != nullptr) + { + CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effOpen, 0, 0, 0, 0, exception); + plug->pluginId1 = pEffect->magic; + plug->pluginId2 = pEffect->uniqueID; + + GetPluginInformation(maskCrashes, pEffect, *plug); + #ifdef VST_LOG - intptr_t nver = CVstPlugin::DispatchSEH(pEffect, Vst::effGetVstVersion, 0,0, nullptr, 0, exception); - if (!nver) nver = pEffect->version; - MPT_LOG(LogDebug, "VST", MPT_UFORMAT("{}: v{}.0, {} in, {} out, {} programs, {} params, flags=0x{} realQ={} offQ={}")( - plug->libraryName, nver, - pEffect->numInputs, pEffect->numOutputs, - mpt::ufmt::dec0<2>(pEffect->numPrograms), mpt::ufmt::dec0<2>(pEffect->numParams), - mpt::ufmt::HEX0<4>(static_cast<int32>(pEffect->flags)), pEffect->realQualities, pEffect->offQualities)); + intptr_t nver = CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effGetVstVersion, 0,0, nullptr, 0, exception); + if (!nver) nver = pEffect->version; + MPT_LOG(LogDebug, "VST", MPT_UFORMAT("{}: v{}.0, {} in, {} out, {} programs, {} params, flags=0x{} realQ={} offQ={}")( + plug->libraryName, nver, + pEffect->numInputs, pEffect->numOutputs, + mpt::ufmt::dec0<2>(pEffect->numPrograms), mpt::ufmt::dec0<2>(pEffect->numParams), + mpt::ufmt::HEX0<4>(static_cast<int32>(pEffect->flags)), pEffect->realQualities, pEffect->offQualities)); #endif // VST_LOG - CVstPlugin::DispatchSEH(pEffect, Vst::effClose, 0, 0, 0, 0, exception); + CVstPlugin::DispatchSEH(maskCrashes, pEffect, Vst::effClose, 0, 0, 0, 0, exception); - validPlug = true; + validPlug = true; + } + } - FreeLibrary(hLib); if(exception != 0) { @@ -672,6 +680,8 @@ } #ifdef MODPLUG_TRACKER + bool maskCrashes = TrackerSettings::Instance().BrokenPluginsWorkaroundVSTMaskAllCrashes; + if(!pFound && (mixPlugin.GetLibraryName() != U_(""))) { // Try finding the plugin DLL in the plugin directory or plugin cache instead. @@ -682,7 +692,7 @@ } fullPath += mpt::PathString::FromUnicode(mixPlugin.GetLibraryName()) + P_(".dll"); - pFound = AddPlugin(fullPath); + pFound = AddPlugin(fullPath, maskCrashes); if(!pFound) { // Try plugin cache (search for library name) @@ -696,7 +706,7 @@ fullPath = theApp.PathInstallRelativeToAbsolute(fullPath); if(fullPath.IsFile()) { - pFound = AddPlugin(fullPath); + pFound = AddPlugin(fullPath, maskCrashes); } } } @@ -710,18 +720,18 @@ HINSTANCE hLibrary = nullptr; bool validPlugin = false; - pEffect = CVstPlugin::LoadPlugin(*pFound, hLibrary, TrackerSettings::Instance().bridgeAllPlugins); + pEffect = CVstPlugin::LoadPlugin(maskCrashes, *pFound, hLibrary, TrackerSettings::Instance().bridgeAllPlugins); if(pEffect != nullptr && pEffect->dispatcher != nullptr && pEffect->magic == Vst::kEffectMagic) { validPlugin = true; - GetPluginInformation(pEffect, *pFound); + GetPluginInformation(maskCrashes, pEffect, *pFound); // Update cached information pFound->WriteToCache(); - CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(hLibrary, *pFound, mixPlugin, *pEffect, sndFile); + CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(maskCrashes, hLibrary, *pFound, mixPlugin, *pEffect, sndFile); if(pVstPlug == nullptr) { validPlugin = false; Index: soundlib/plugins/PluginManager.h =================================================================== --- soundlib/plugins/PluginManager.h (revision 13970) +++ soundlib/plugins/PluginManager.h (working copy) @@ -160,7 +160,7 @@ size_t size() const { return pluginList.size(); } bool IsValidPlugin(const VSTPluginLib *pLib) const; - VSTPluginLib *AddPlugin(const mpt::PathString &dllPath, const mpt::ustring &tags = mpt::ustring(), bool fromCache = true, bool *fileFound = nullptr); + VSTPluginLib *AddPlugin(const mpt::PathString &dllPath, bool maskCrashes, const mpt::ustring &tags = mpt::ustring(), bool fromCache = true, bool *fileFound = nullptr); bool RemovePlugin(VSTPluginLib *); bool CreateMixPlugin(SNDMIXPLUGIN &, CSoundFile &); void OnIdle(); |
|
Comited as r13996 (1.30.00.23). |
|
Forum thread: https://forum.openmpt.org/index.php?topic=6537.0 |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2020-12-22 17:04 | manx | New Issue | |
2020-12-22 17:04 | manx | Status | new => assigned |
2020-12-22 17:04 | manx | Assigned To | => manx |
2020-12-22 17:04 | manx | Relationship added | related to 0001291 |
2020-12-22 17:05 | manx | Note Added: 0004557 | |
2020-12-22 17:05 | manx | File Added: vst-seh-v10.patch | |
2020-12-22 17:06 | manx | Status | assigned => feedback |
2020-12-30 09:22 | manx | Note Added: 0004584 | |
2020-12-30 11:04 | manx | Note Added: 0004587 | |
2021-01-10 18:28 | manx | Status | feedback => resolved |
2021-01-10 18:28 | manx | Resolution | open => fixed |
2021-01-10 18:28 | manx | Fixed in Version | => OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) |