From: <sag...@us...> - 2015-06-09 20:36:49
|
Revision: 5286 http://sourceforge.net/p/modplug/code/5286 Author: saga-games Date: 2015-06-09 20:36:42 +0000 (Tue, 09 Jun 2015) Log Message: ----------- [Fix] Avoid crashes when VST calls IO change opcode (possibly introduced with recent message dispatching code, but could have happened at any time before as well) Modified Paths: -------------- trunk/OpenMPT/build/premake/mpt-PluginBridge.lua trunk/OpenMPT/build/vs2008/PluginBridge.vcproj trunk/OpenMPT/build/vs2010/PluginBridge.vcxproj trunk/OpenMPT/build/vs2012/PluginBridge.vcxproj trunk/OpenMPT/build/vs2013/PluginBridge.vcxproj trunk/OpenMPT/build/vs2015/PluginBridge.vcxproj trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/pluginBridge/AEffectWrapper.h trunk/OpenMPT/pluginBridge/Bridge.cpp trunk/OpenMPT/pluginBridge/BridgeCommon.h trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp trunk/OpenMPT/pluginBridge/BridgeWrapper.h trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj.filters Added Paths: ----------- trunk/OpenMPT/pluginBridge/BridgeOpCodes.h Modified: trunk/OpenMPT/build/premake/mpt-PluginBridge.lua =================================================================== --- trunk/OpenMPT/build/premake/mpt-PluginBridge.lua 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/premake/mpt-PluginBridge.lua 2015-06-09 20:36:42 UTC (rev 5286) @@ -15,6 +15,7 @@ "../../pluginBridge/Bridge.cpp", "../../pluginBridge/Bridge.h", "../../pluginBridge/BridgeCommon.h", + "../../pluginBridge/BridgeOpCodes.h", "../../pluginBridge/PluginBridge.rc", } defines { "MODPLUG_TRACKER" } Modified: trunk/OpenMPT/build/vs2008/PluginBridge.vcproj =================================================================== --- trunk/OpenMPT/build/vs2008/PluginBridge.vcproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/vs2008/PluginBridge.vcproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -706,6 +706,10 @@ > </File> <File + RelativePath="..\..\pluginBridge\BridgeOpCodes.h" + > + </File> + <File RelativePath="..\..\pluginBridge\PluginBridge.rc" > </File> Modified: trunk/OpenMPT/build/vs2010/PluginBridge.vcxproj =================================================================== --- trunk/OpenMPT/build/vs2010/PluginBridge.vcxproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/vs2010/PluginBridge.vcxproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -432,6 +432,7 @@ <ClInclude Include="..\..\pluginBridge\AEffectWrapper.h" /> <ClInclude Include="..\..\pluginBridge\Bridge.h" /> <ClInclude Include="..\..\pluginBridge\BridgeCommon.h" /> + <ClInclude Include="..\..\pluginBridge\BridgeOpCodes.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\pluginBridge\Bridge.cpp" /> Modified: trunk/OpenMPT/build/vs2012/PluginBridge.vcxproj =================================================================== --- trunk/OpenMPT/build/vs2012/PluginBridge.vcxproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/vs2012/PluginBridge.vcxproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -440,6 +440,7 @@ <ClInclude Include="..\..\pluginBridge\AEffectWrapper.h" /> <ClInclude Include="..\..\pluginBridge\Bridge.h" /> <ClInclude Include="..\..\pluginBridge\BridgeCommon.h" /> + <ClInclude Include="..\..\pluginBridge\BridgeOpCodes.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\pluginBridge\Bridge.cpp" /> Modified: trunk/OpenMPT/build/vs2013/PluginBridge.vcxproj =================================================================== --- trunk/OpenMPT/build/vs2013/PluginBridge.vcxproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/vs2013/PluginBridge.vcxproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -441,6 +441,7 @@ <ClInclude Include="..\..\pluginBridge\AEffectWrapper.h" /> <ClInclude Include="..\..\pluginBridge\Bridge.h" /> <ClInclude Include="..\..\pluginBridge\BridgeCommon.h" /> + <ClInclude Include="..\..\pluginBridge\BridgeOpCodes.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\pluginBridge\Bridge.cpp" /> Modified: trunk/OpenMPT/build/vs2015/PluginBridge.vcxproj =================================================================== --- trunk/OpenMPT/build/vs2015/PluginBridge.vcxproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/build/vs2015/PluginBridge.vcxproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -441,6 +441,7 @@ <ClInclude Include="..\..\pluginBridge\AEffectWrapper.h" /> <ClInclude Include="..\..\pluginBridge\Bridge.h" /> <ClInclude Include="..\..\pluginBridge\BridgeCommon.h" /> + <ClInclude Include="..\..\pluginBridge\BridgeOpCodes.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\pluginBridge\Bridge.cpp" /> Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2015-06-09 20:36:42 UTC (rev 5286) @@ -26,6 +26,7 @@ #include "../common/mptFileIO.h" #include "../common/FileReader.h" #include "FileDialog.h" +#include "../pluginBridge/BridgeOpCodes.h" #include "../soundlib/plugins/OpCodes.h" #include "../soundlib/mod_specifications.h" @@ -165,7 +166,8 @@ // Time signature. numerator = rows per beats / rows pear measure (should sound somewhat logical to you). // the denominator is a bit more tricky, since it cannot be set explicitely. so we just assume quarters for now. - timeInfo.timeSigNumerator = sndFile.m_PlayState.m_nCurrentRowsPerMeasure / std::max(sndFile.m_PlayState.m_nCurrentRowsPerBeat, ROWINDEX(1)); + ROWINDEX rpb = std::max(sndFile.m_PlayState.m_nCurrentRowsPerBeat, ROWINDEX(1)); + timeInfo.timeSigNumerator = std::max(sndFile.m_PlayState.m_nCurrentRowsPerMeasure, rpb) / rpb; timeInfo.timeSigDenominator = 4; //gcd(pSndFile->m_nCurrentRowsPerMeasure, pSndFile->m_nCurrentRowsPerBeat); } } @@ -1154,11 +1156,11 @@ CString formattedName; if((unsigned char)rawname[0] < ' ') { - formattedName.Format("%02d - Program %d", index, index); + formattedName.Format("%02u - Program %u", index, index); } else { - formattedName.Format("%02d - %s", index, rawname); + formattedName.Format("%02u - %s", index, rawname); } return formattedName; @@ -1194,14 +1196,8 @@ //CVstPluginManager::ReportPlugException("Exception in getParameter (Plugin=\"%s\")!\n", m_Factory.szLibraryName); } } - //rewbs.VSTcompliance - if (fResult<0.0f) - return 0.0f; - else if (fResult>1.0f) - return 1.0f; - else - //end rewbs.VSTcompliance - return fResult; + Limit(fResult, 0.0f, 1.0f); + return fResult; } @@ -1482,15 +1478,15 @@ // If the plug is found & ok, continue if(m_pProcessFP != nullptr && (mixBuffer.GetInputBufferArray()) && mixBuffer.GetOutputBufferArray() && m_pMixStruct != nullptr) { - + VstInt32 numInputs = m_Effect.numInputs, numOutputs = m_Effect.numOutputs; //RecalculateGain(); // Merge stereo input before sending to the plug if the plug can only handle one input. - if (m_Effect.numInputs == 1) + if (numInputs == 1) { for (size_t i = 0; i < nSamples; i++) { - m_MixState.pOutBufferL[i] = 0.5f * m_MixState.pOutBufferL[i] + 0.5f * m_MixState.pOutBufferR[i]; + m_MixState.pOutBufferL[i] = 0.5f * (m_MixState.pOutBufferL[i] + m_MixState.pOutBufferR[i]); } } @@ -1515,15 +1511,15 @@ ASSERT(outputBuffers != nullptr); // Mix outputs of multi-output VSTs: - if(m_Effect.numOutputs > 2) + if(numOutputs > 2) { // first, mix extra outputs on a stereo basis - VstInt32 numOutputs = m_Effect.numOutputs; + VstInt32 outs = numOutputs; // so if nOuts is not even, let process the last output later - if((numOutputs % 2u) == 1) numOutputs--; + if((outs % 2u) == 1) outs--; // mix extra stereo outputs - for(VstInt32 iOut = 2; iOut < numOutputs; iOut++) + for(VstInt32 iOut = 2; iOut < outs; iOut++) { for(size_t i = 0; i < nSamples; i++) { @@ -1532,21 +1528,21 @@ } // if m_Effect.numOutputs is odd, mix half the signal of last output to each channel - if(numOutputs != m_Effect.numOutputs) + if(outs != numOutputs) { // trick : if we are here, numOutputs = m_Effect.numOutputs - 1 !!! for(size_t i = 0; i < nSamples; i++) { - float v = 0.5f * outputBuffers[numOutputs][i]; + float v = 0.5f * outputBuffers[outs][i]; outputBuffers[0][i] += v; outputBuffers[1][i] += v; } } } - if(m_Effect.numOutputs != 0) + if(numOutputs != 0) { - ProcessMixOps(pOutL, pOutR, outputBuffers[0], outputBuffers[m_Effect.numOutputs > 1 ? 1 : 0], nSamples); + ProcessMixOps(pOutL, pOutR, outputBuffers[0], outputBuffers[numOutputs > 1 ? 1 : 0], nSamples); } // If dry mix is ticked, we add the unprocessed buffer, @@ -1559,6 +1555,12 @@ pOutR[i] += m_MixState.pOutBufferR[i]; } } + + // If the I/O format of the bridge changed in the meanwhile, update it now. + if(isBridged && Dispatch(effVendorSpecific, kVendorOpenMPT, kCloseOldProcessingMemory, nullptr, 0.0f) != 0) + { + InitializeIOBuffers(); + } } vstEvents.Clear(); @@ -2018,6 +2020,7 @@ pModDoc->RecordParamChange(GetSlot(), param); } + // TODO: This should rather be posted to the GUI thread! CAbstractVstEditor *pVstEditor = GetEditor(); if(pVstEditor && pVstEditor->m_hWnd) Modified: trunk/OpenMPT/pluginBridge/AEffectWrapper.h =================================================================== --- trunk/OpenMPT/pluginBridge/AEffectWrapper.h 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/AEffectWrapper.h 2015-06-09 20:36:42 UTC (rev 5286) @@ -94,17 +94,6 @@ #pragma pack(pop) -enum VendorSpecificOpCodes -{ - kUpdateEffectStruct = 0, - kUpdateProcessingBuffer, - kGetWrapperPointer, - kUpdateEventMemName, - - kVendorOpenMPT = CCONST('O', 'M', 'P', 'T'), -}; - - // Translate a VSTEvents struct to bridge format (placed in data vector) static void TranslateVSTEventsToBridge(std::vector<char> &data, const VstEvents *events, int32_t targetPtrSize) { Modified: trunk/OpenMPT/pluginBridge/Bridge.cpp =================================================================== --- trunk/OpenMPT/pluginBridge/Bridge.cpp 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/Bridge.cpp 2015-06-09 20:36:42 UTC (rev 5286) @@ -13,7 +13,7 @@ // Optimize out audioMasterProcessEvents the same way as effProcessEvents? // Find a nice solution for audioMasterIdle that doesn't break TAL-Elek7ro-II // Maybe don't keep opening and closing aux mem files - but they are rarely needed, so would this actually be worth it? -// Kirnu GUI deadlocks during playback +// Kirnu and Combo F GUI deadlocks during playback // Low priority: // Speed up things like consecutive calls to CVstPlugin::GetFormattedProgramName by a custom opcode (is this necessary?) @@ -934,7 +934,7 @@ MPT_FALLTHROUGH; case audioMasterIOChanged: // We need to be sure that the new values are known to the master. - if(!processing && nativeEffect != nullptr) + if(nativeEffect != nullptr) { UpdateEffectStruct(); CreateProcessingFile(dispatchData); Modified: trunk/OpenMPT/pluginBridge/BridgeCommon.h =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeCommon.h 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/BridgeCommon.h 2015-06-09 20:36:42 UTC (rev 5286) @@ -27,6 +27,7 @@ } #include "AEffectWrapper.h" +#include "BridgeOpCodes.h" #include "../common/thread.h" @@ -182,6 +183,16 @@ } bool Good() const { return view != nullptr; } + + // Make a copy and detach it from the other object + void CopyFrom(MappedMemory &other) + { + Close(); + mapFile = other.mapFile; + view = other.view; + other.mapFile = nullptr; + other.view = nullptr; + } }; Added: trunk/OpenMPT/pluginBridge/BridgeOpCodes.h =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeOpCodes.h (rev 0) +++ trunk/OpenMPT/pluginBridge/BridgeOpCodes.h 2015-06-09 20:36:42 UTC (rev 5286) @@ -0,0 +1,25 @@ +/* + * BridgeOpCodes.h + * --------------- + * Purpose: Various dispatch opcodes for communication between OpenMPT and its plugin bridge. + * Notes : (currently none) + * Authors: Johannes Schultz (OpenMPT Devs) + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#define VST_FORCE_DEPRECATED 0 +#include "../include/vstsdk2.4/pluginterfaces/vst2.x/aeffectx.h" + +enum VendorSpecificOpCodes +{ + kUpdateEffectStruct = 0, + kUpdateProcessingBuffer, + kGetWrapperPointer, + kUpdateEventMemName, + kCloseOldProcessingMemory, + + kVendorOpenMPT = CCONST('O', 'M', 'P', 'T'), +}; Property changes on: trunk/OpenMPT/pluginBridge/BridgeOpCodes.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-chdr \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp 2015-06-09 20:36:42 UTC (rev 5286) @@ -468,8 +468,23 @@ } MPT_FALLTHROUGH; case audioMasterIOChanged: - // Set up new processing file - processMem.Open(reinterpret_cast<wchar_t *>(ptr)); + { + // If the song is playing, the rendering thread might be active at the moment, + // so we should keep the current processing memory alive until it is done for sure. + const CVstPlugin *plug = FromVstPtr<CVstPlugin>(sharedMem->effect.resvd1); + const bool isPlaying = plug != nullptr && plug->IsSongPlaying(); + if(isPlaying) + { + oldProcessMem.CopyFrom(processMem); + } + // Set up new processing file + processMem.Open(reinterpret_cast<wchar_t *>(ptr)); + if(isPlaying) + { + msg->result = 1; + return; + } + } break; case audioMasterOpenFileSelector: @@ -644,9 +659,20 @@ break; case effVendorSpecific: - if(index == kVendorOpenMPT && value == kGetWrapperPointer) + if(index == kVendorOpenMPT) { - return ToVstPtr<BridgeWrapper>(that); + switch(value) + { + case kGetWrapperPointer: + return ToVstPtr<BridgeWrapper>(that); + + case kCloseOldProcessingMemory: + { + VstIntPtr result = that->oldProcessMem.Good(); + that->oldProcessMem.Close(); + return result; + } + } } break; Modified: trunk/OpenMPT/pluginBridge/BridgeWrapper.h =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeWrapper.h 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/BridgeWrapper.h 2015-06-09 20:36:42 UTC (rev 5286) @@ -63,6 +63,7 @@ { protected: Event sigAutomation; + MappedMemory oldProcessMem; bool isSettingProgram; ERect editRect; Modified: trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj =================================================================== --- trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj 2015-06-09 20:36:42 UTC (rev 5286) @@ -206,6 +206,7 @@ <ClInclude Include="AEffectWrapper.h" /> <ClInclude Include="Bridge.h" /> <ClInclude Include="BridgeCommon.h" /> + <ClInclude Include="BridgeOpCodes.h" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="PluginBridge.rc" /> Modified: trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj.filters =================================================================== --- trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj.filters 2015-06-09 19:13:05 UTC (rev 5285) +++ trunk/OpenMPT/pluginBridge/PluginBridge.vcxproj.filters 2015-06-09 20:36:42 UTC (rev 5286) @@ -10,6 +10,9 @@ <ClInclude Include="Bridge.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="BridgeOpCodes.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Filter Include="Header Files"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |