Experimental support for the Windows Runtime MIDI API


Ah no… Now it’s really f*** up. After having to update to the new asio sdk (which of course has nothing to do with this), the Device combo is empty and when trying to select my Focusrite usb driver, I get the Juce message “Error when trying to open audio device! No such device”. Any subseq try to get in contact with my Asio audio device fail.

When inspecting the debug output console i find following disturbing lines repeated twice when starting my app

Exception thrown at 0x00007FF925CF7788 (KernelBase.dll) in Daw2.exe: 0x40080201: WinRT originate error (parameters: 0x0000000080040155, 0x000000000000004A, 0x00000015B07FD650).

Just to be sure I myself wasn’t to blame for this… misfortune, I replaced the new juce_win32_Midi.cpp (that’s the file right?) with the previous one, and voila, it works again.

To quote Clouseau, Something must be terribly wrong here…:slight_smile:


Ouch. Sorry about that.

Please try again with the latest develop tip.


Thanks. Works now! Apart from the mysterious numbering, that is, but that’s no big concern of mine anyway…


Some more feedback…
I get an access violation whenever I unplug my USB midi input device from my app.

It emanates from

HRESULT removeDevice (IDeviceInformationUpdate* removedDeviceInfo)
    const ScopedLock lock (deviceChanges); <<< access violation

I’ll gladly provide you with more info if you can’t provide your own crash by simply unplugging your midi device.


Another regression with the previous fix :unamused:

Everything should be working on the develop branch now!


Thanks, now the violent error is gone…



I’m finding the new API a lot more stable when sending sysex data very rapidly from USB-MIDI devices (hundreds of kilobytes of sysex data per second).

Legacy API is subject to very serious packet loss in these situations. However, I’m not sure whether this is a low-level problem or a JUCE Win32 MIDI problem (perhaps too small or to few low-level buffers?)

Considering my packet loss problem, I’m wondering whether the “fallback” solution would re-introduce these problems even when compiling with the new JUCE API. Can you recommend a way to test the new JUCE API specifically with the fallback? Old windows version but same binary? Or is there a smarter way?


My testing has shown that sysex messages shorter then 19 bytes fail to send with the new API, longer messages (which are generally split into multiple parts at a lower level than JUCE) seem to work well.

The fallback is the same as simply not using the new API. When you select the new Windows API in the Projucer then your application will check if the API is available at runtime and, if it is, it will use it, otherwise it will use the older JUCE MIDI code.

An old Windows version but the same binary would do it, or just de-select JUCE_USE_WINRT_MIDI.


Not being able to send short messages is indeed a serious problem. But I actually see a problem also when sending large data. The new API won’t even attempt to transmit a sysex message larger than 256 bytes.

For example:

uint8 testData[512 - 2];
std::fill(testData, testData + sizeof(testData), 0x10);
midiOut->sendMessageNow(MidiMessage::createSysExMessage(testData, sizeof(testData)));

The function WinRTOutputWrapper::sendMessageNow() asserts at this line:

void sendMessageNow (const MidiMessage& message) override
    const UINT32 numBytes = message.getRawDataSize();
    HRESULT hr = buffer->put_Length (numBytes);
    if (FAILED (hr))
        jassertfalse; <------ HERE

    memcpy_s (bufferData, numBytes, message.getRawData(), numBytes);

    midiOutPort->SendBuffer (buffer);

The HRESULT error code is: E_INVALIDARG (One or more arguments are invalid.)

Reception of large sysex data works flawlessly, so it is really unfortunate that it is instead problematic to send data. Legacy API would send large data without any problems, but wouldn’t receive successfully =)


Aha, I missed the obvious. After some more digging I see that the max buffer size is indeed determined inside the JUCE library code in the MidiRTOutputWrapper constructor.

Would you consider increasing the this from 256 bytes to perhaps 64k?

HRESULT hr = bufferFactory->Create (static_cast<UINT32> (65536), buffer.resetAndGetPointerAddress());

Or perhaps a configurable number depending on the application? We are doing sample dumps to hardware, requiring quite big packets to be efficient.

I’m using 64k buffers now in my modified JUCE class, works fine!


I’d certainly consider it, but there was a motivation for choosing 256 that I’ve since forgotten.

Does everything work as expected for you if you change it?


Sorry, edited message instead of replying. 64k works well, also every other 2^N size below that, run a lot of tests.


OK, I’ll revisit this tomorrow and see if I can work out why I picked 256.






We have been testing the new API using a connected Bluetooth LE device. We have noticed that when we send MIDI Sysex messages to a Bluetooth LE device only part of the message arrives at the receiver, e.g. if we send a short four byte message only the first two bytes are received.

Have you guys discovered any work arounds for this problem? The only work around that we have come up with is to use the Windows Bluetooth SDKs directly…


We’ve not found anything better than that.

However, there is some related good news on the horizon - Microsoft appear to have fixed this issue in their latest developer preview, which means it’s likely this will be fixed in the next major release. Once that’s verified we’ll investigate enabling the new MIDI API by default for new Windows versions.


Hi, what’s the current status on this? Am I correct in thinking that this will also provide multi-client access to a MIDI port? thx


Microsoft were told about the SysEx hanging problem in 2015. They are also aware of the device enumeration problem. In their forums, they say they’re working on it. I have to wonder what takes three years to fix two crippling problems.


Their attitude to MIDI is perplexing to say the least. I can’t believe that we still need things like loopmidi to create virtual MIDI ports also.