From: <sag...@us...> - 2012-03-07 23:51:29
|
Revision: 1209 http://modplug.svn.sourceforge.net/modplug/?rev=1209&view=rev Author: saga-games Date: 2012-03-07 23:51:23 +0000 (Wed, 07 Mar 2012) Log Message: ----------- [Fix] Added some thread saftey to the VST event queue - using f.e. the MID2VST could easily corrupt the deque when sending lots of MIDI events through that plugin. Modified Paths: -------------- trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/soundlib/PluginEventQueue.h Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2012-03-07 23:21:34 UTC (rev 1208) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2012-03-07 23:51:23 UTC (rev 1209) @@ -2006,12 +2006,8 @@ m_pEffect->dispatcher(m_pEffect, effProcessEvents, 0, 0, &vstEvents, 0); } catch (...) { - CVstPluginManager::ReportPlugException("Exception in ProcessVSTEvents() (Plugin=%s, numEvents:%d, MidicodeCh:%d, MidicodeEv:%d, MidicodeNote:%d, MidiCodeVel:%d)\n", - m_pFactory->szLibraryName, vstEvents.numEvents, - (((VstMidiEvent *)(vstEvents.events[0]))->midiData[0]) & 0x0f, - (((VstMidiEvent *)(vstEvents.events[0]))->midiData[0]) & 0xf0, - (((VstMidiEvent *)(vstEvents.events[0]))->midiData[1]) & 0xff, - (((VstMidiEvent *)(vstEvents.events[0]))->midiData[2]) & 0xff); + CVstPluginManager::ReportPlugException("Exception in ProcessVSTEvents() (Plugin=%s, numEvents:%d)\n", + m_pFactory->szLibraryName, vstEvents.GetNumEvents()); } } } @@ -2299,9 +2295,8 @@ bool insertAtFront = ((dwMidiCode & 0xF0) == 0x80); VstMidiEvent event; - MemsetZero(event); event.type = kVstMidiType; - event.byteSize = 24; + event.byteSize = sizeof(VstMidiEvent); event.deltaFrames = 0; event.flags = 0; event.noteLength = 0; Modified: trunk/OpenMPT/soundlib/PluginEventQueue.h =================================================================== --- trunk/OpenMPT/soundlib/PluginEventQueue.h 2012-03-07 23:21:34 UTC (rev 1208) +++ trunk/OpenMPT/soundlib/PluginEventQueue.h 2012-03-07 23:51:23 UTC (rev 1209) @@ -30,8 +30,10 @@ // Alternative, easy to use implementation of VstEvents struct. template <size_t N> -struct PluginEventQueue +class PluginEventQueue { +protected: + typedef VstMidiEvent BiggestVstEvent; static_assert(sizeof(BiggestVstEvent) >= sizeof(VstEvent) && sizeof(BiggestVstEvent) >= sizeof(VstMidiEvent) @@ -40,27 +42,43 @@ VstInt32 numEvents; ///< number of Events in array VstIntPtr reserved; ///< zero (Reserved for future use) - VstEvent* events[N]; ///< event pointer array + VstEvent *events[N]; ///< event pointer array std::deque<BiggestVstEvent> eventQueue; // Here we store our events. + CRITICAL_SECTION criticalSection; +public: + PluginEventQueue() { numEvents = 0; reserved = nullptr; MemsetZero(events); + MemsetZero(criticalSection); + InitializeCriticalSection(&criticalSection); } + ~PluginEventQueue() + { + DeleteCriticalSection(&criticalSection); + } + + size_t GetNumEvents() + { + return numEvents; + } + // Add a VST event to the queue. Returns true on success. bool Enqueue(const VstEvent &event, bool insertFront = false) { VstMidiEvent midiEvent; - memcpy(&midiEvent, &event, sizeof(event)); + memcpy(&midiEvent, &event, min(event.byteSize, sizeof(event))); ASSERT(event.byteSize == sizeof(event)); return Enqueue(midiEvent, insertFront); } bool Enqueue(const VstMidiEvent &event, bool insertFront = false) { static_assert(sizeof(BiggestVstEvent) <= sizeof(VstMidiEvent), "Also check implementation here."); + EnterCriticalSection(&criticalSection); if(insertFront) { eventQueue.push_front(event); @@ -68,12 +86,13 @@ { eventQueue.push_back(event); } + LeaveCriticalSection(&criticalSection); return true; } bool Enqueue(const VstMidiSysexEvent &event, bool insertFront = false) { VstMidiEvent midiEvent; - memcpy(&midiEvent, &event, sizeof(event)); + memcpy(&midiEvent, &event, min(event.byteSize, sizeof(event))); ASSERT(event.byteSize == sizeof(event)); return Enqueue(midiEvent, insertFront); } @@ -81,22 +100,26 @@ // Set up the queue for transmitting to the plugin. Returns number of elements that are going to be transmitted. VstInt32 Finalise() { + EnterCriticalSection(&criticalSection); numEvents = min(eventQueue.size(), N); for(VstInt32 i = 0; i < numEvents; i++) { events[i] = reinterpret_cast<VstEvent *>(&eventQueue[i]); } + LeaveCriticalSection(&criticalSection); return numEvents; } // Remove transmitted events from the queue void Clear() { + EnterCriticalSection(&criticalSection); if(numEvents) { eventQueue.erase(eventQueue.begin(), eventQueue.begin() + numEvents); numEvents = 0; } + LeaveCriticalSection(&criticalSection); } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |