As a side project, I am implementing a MIDI matrix to interconnect a number of MIDI keyboards with sound sources. The key requirement here is to echo MIDI data received on an input port to a selected output port.
Having created the necessary P/Invoke declarations & wrappers, I notice that the Win32 MIDI documentation for MidiInProc
states: "Applications should not call any multimedia functions from inside the callback function, as doing so can cause a deadlock".
Given that it is unsafe to call midiOutShortMsg
from within a MidiInProc
, my current solution is to write MIDI data to a queue and set an event. A worker thread waits on the event and calls midiOutShortMsg
. The general idea is this:-
static void InputCallback( int hMidiIn, uint wMsg, uint dwInstance, uint dwParam1, uint dwParam2 )
{
if( wMsg == MM_MIM_DATA )
{
data.EnQueue( dwParam1 ); //data is a Queue<uint>
dataReady.Set(); //dataReady is AutoResetEvent
}
}
void ThreadProc
{
while( !_done )
{
dataReady.WaitOne();
midiOutShortMsg( hMidiOut, data.DeQueue() );
}
}
However, whilst this has been working fine in testing, there appears to be a window of opportunity between the call to dataReady.Set()
and InputCallBack
returning during which preemption could allow the worker thread to call midiOutShortMsg
(albeit in another thread).
Is this approach safe?