From: <sag...@us...> - 2013-03-22 17:57:48
|
Revision: 1623 http://sourceforge.net/p/modplug/code/1623 Author: saga-games Date: 2013-03-22 17:57:40 +0000 (Fri, 22 Mar 2013) Log Message: ----------- [Imp] MIDI Input / Output plugin also stores program name now. [Fix] MIDI Input / Output plugin could crash when changing input/output devices while something was playing. Modified Paths: -------------- trunk/OpenMPT/plugins/MidiInOut/MidiInOut.cpp trunk/OpenMPT/plugins/MidiInOut/MidiInOut.h Added Paths: ----------- trunk/OpenMPT/common/mutex.h Added: trunk/OpenMPT/common/mutex.h =================================================================== --- trunk/OpenMPT/common/mutex.h (rev 0) +++ trunk/OpenMPT/common/mutex.h 2013-03-22 17:57:40 UTC (rev 1623) @@ -0,0 +1,51 @@ +/* + * mutex.h + * ------- + * Purpose: Partially implement c++ mutexes as far as openmpt needs them. Can eventually go away when we only support c++11 compilers some time. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#pragma once + +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRALEAN +#define NOMINMAX +#include <windows.h> + +namespace Util { + +// compatible with c++11 std::mutex, can eventually be replaced without touching any usage site +class mutex { +private: + CRITICAL_SECTION impl; +public: + mutex() { InitializeCriticalSection(&impl); } + ~mutex() { DeleteCriticalSection(&impl); } + void lock() { EnterCriticalSection(&impl); } + void unlock() { LeaveCriticalSection(&impl); } +}; + +// compatible with c++11 std::recursive_mutex, can eventually be replaced without touching any usage site +class recursive_mutex { +private: + CRITICAL_SECTION impl; +public: + recursive_mutex() { InitializeCriticalSection(&impl); } + ~recursive_mutex() { DeleteCriticalSection(&impl); } + void lock() { EnterCriticalSection(&impl); } + void unlock() { LeaveCriticalSection(&impl); } +}; + +// compatible with c++11 std::lock_guard, can eventually be replaced without touching any usage site +template< typename mutex_type > +class lock_guard { +private: + mutex_type & mutex; +public: + lock_guard( mutex_type & m ) : mutex(m) { mutex.lock(); } + ~lock_guard() { mutex.unlock(); } +}; + +} // namespace Util Modified: trunk/OpenMPT/plugins/MidiInOut/MidiInOut.cpp =================================================================== --- trunk/OpenMPT/plugins/MidiInOut/MidiInOut.cpp 2013-03-22 15:19:43 UTC (rev 1622) +++ trunk/OpenMPT/plugins/MidiInOut/MidiInOut.cpp 2013-03-22 17:57:40 UTC (rev 1623) @@ -47,8 +47,6 @@ chunk = nullptr; isProcessing = false; isBypassed = false; - OpenDevice(inputDevice.index, true); - OpenDevice(outputDevice.index, true); vst_strncpy(programName, "Default", kVstMaxProgNameLen); // default program name } @@ -85,7 +83,9 @@ VstInt32 MidiInOut::getChunk(void **data, bool /*isPreset*/) //---------------------------------------------------------- { - VstInt32 byteSize = 5 * sizeof(VstInt32) + const VstInt32 programNameLen = strlen(programName); + VstInt32 byteSize = 8 * sizeof(VstInt32) + + programNameLen + inputDevice.name.size() + outputDevice.name.size(); @@ -95,12 +95,16 @@ { VstInt32 *header = reinterpret_cast<VstInt32 *>(chunk); header[0] = cEffect.version; - header[1] = inputDevice.index; - header[2] = inputDevice.name.size(); - header[3] = outputDevice.index; - header[4] = outputDevice.name.size(); - strncpy(chunk + 5 * sizeof(VstInt32), inputDevice.name.c_str(), header[2]); - strncpy(chunk + 5 * sizeof(VstInt32) + header[2], outputDevice.name.c_str(), header[4]); + header[1] = 1; // Number of programs + header[2] = programNameLen; + header[3] = inputDevice.index; + header[4] = inputDevice.name.size(); + header[5] = outputDevice.index; + header[6] = outputDevice.name.size(); + header[7] = 0; // Reserved + strncpy(chunk + 8 * sizeof(VstInt32), programName, programNameLen); + strncpy(chunk + 8 * sizeof(VstInt32) + programNameLen, inputDevice.name.c_str(), header[4]); + strncpy(chunk + 8 * sizeof(VstInt32) + programNameLen + header[2], outputDevice.name.c_str(), header[6]); return byteSize; } else { @@ -112,7 +116,7 @@ VstInt32 MidiInOut::setChunk(void *data, VstInt32 byteSize, bool /*isPreset*/) //---------------------------------------------------------------------------- { - if(byteSize < 5 * sizeof(VstInt32)) + if(byteSize < 8 * sizeof(VstInt32)) { return 0; } @@ -125,13 +129,14 @@ return 0; } - VstInt32 inStrSize = std::min(header[2], byteSize - VstInt32(5 * sizeof(VstInt32))); - VstInt32 outStrSize = std::min(header[4], byteSize - VstInt32(5 * sizeof(VstInt32) + inStrSize)); - PmDeviceID inID = header[1]; - PmDeviceID outID = header[3]; + VstInt32 nameStrSize = std::min(header[2], byteSize - VstInt32(8 * sizeof(VstInt32))); + VstInt32 inStrSize = std::min(header[4], byteSize - VstInt32(8 * sizeof(VstInt32) - nameStrSize)); + VstInt32 outStrSize = std::min(header[6], byteSize - VstInt32(8 * sizeof(VstInt32) - nameStrSize - inStrSize)); + PmDeviceID inID = header[3]; + PmDeviceID outID = header[5]; - const char *inStr = reinterpret_cast<const char *>(data) + 5 * sizeof(VstInt32); - const char *outStr = reinterpret_cast<const char *>(data) + 5 * sizeof(VstInt32) + inStrSize; + const char *inStr = reinterpret_cast<const char *>(data) + 8 * sizeof(VstInt32) + header[2]; + const char *outStr = reinterpret_cast<const char *>(data) + 8 * sizeof(VstInt32) + header[2] + inStrSize; if(strncmp(inStr, GetDeviceName(inID), inStrSize)) { @@ -281,6 +286,8 @@ return; } + Util::lock_guard<Util::mutex> lock(mutex); + VstEvents events; events.numEvents = 1; events.reserved = 0; @@ -410,6 +417,7 @@ // Don't open MIDI devices if we're not processing. // This has to be done since we receive MIDI events in processReplacing(), // so if no processing is happening, some irrelevant events might be queued until the next processing happens... + Util::lock_guard<Util::mutex> lock(mutex); if(asInputDevice) { result = Pm_OpenInput(&device.stream, newDevice, nullptr, 0, nullptr, nullptr); @@ -438,6 +446,7 @@ { if(device.stream != nullptr) { + Util::lock_guard<Util::mutex> lock(mutex); Pm_Close(device.stream); device.stream = nullptr; } Modified: trunk/OpenMPT/plugins/MidiInOut/MidiInOut.h =================================================================== --- trunk/OpenMPT/plugins/MidiInOut/MidiInOut.h 2013-03-22 15:19:43 UTC (rev 1622) +++ trunk/OpenMPT/plugins/MidiInOut/MidiInOut.h 2013-03-22 17:57:40 UTC (rev 1623) @@ -10,6 +10,7 @@ #pragma once +#include "../common/mutex.h" #include <vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h> #include <portmidi/pm_common/portmidi.h> #include <string> @@ -53,6 +54,7 @@ }; // For getChunk + Util::mutex mutex; char *chunk; // I/O device settings @@ -99,12 +101,12 @@ // MIDI channels virtual VstInt32 getNumMidiInputChannels() { - return (inputDevice.index != noDevice) ? 16 : 0; + return 16; } virtual VstInt32 getNumMidiOutputChannels() { - return (outputDevice.index != noDevice) ? 16 : 0; + return 16; } // Effect name + version stuff This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |