atsushieno / managed-midi

[Past project] Cross-platform MIDI processing library for mono and .NET (ALSA, CoreMIDI, Android, WinMM and UWP).
MIT License
195 stars 26 forks source link

Exception on device disconnect on Windows #49

Closed holly-hacker closed 5 years ago

holly-hacker commented 5 years ago

I run MidiAccessManager.Default.Inputs.ToList() every 500ms, and it crashes with the following stacktrace when a MIDI device gets removed:

System.ComponentModel.Win32Exception: There is no driver installed on your system. (6)
  at Commons.Music.Midi.WinMM.WinMMMidiInput.DieOnError(Int32 code) in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:235
  at Commons.Music.Midi.WinMM.WinMMMidiInput.LongMessageBuffer.AddBuffer() in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:286
  at Commons.Music.Midi.WinMM.WinMMMidiInput.LongMessageBuffer.Recycle() in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:297
  at Commons.Music.Midi.WinMM.WinMMMidiInput.HandleLongData(IntPtr param1, IntPtr param2) in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:147
  at Commons.Music.Midi.WinMM.WinMMMidiInput.HandleMidiInProc(IntPtr midiIn, MidiInMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:171
  at at Commons.Music.Midi.WinMM.WinMMNatives.midiInGetNumDevs()
  at Commons.Music.Midi.WinMM.WinMMMidiAccess.get_Inputs()+MoveNext() in D:\a\1\s\Commons.Music.Midi.DesktopShared\winmm\WinmmMidiAccess.cs:18
  at at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
  at at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
  at at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
  at osu.Framework.Input.Handlers.MidiInputHandler.refreshDevices() in D:\Projects\Git\osu-framework\osu.Framework\Input\Handlers\MidiInputHandler.cs:58

Input from my device works fine, and on Linux I don't have this issue. You can see my usage here.

atsushieno commented 5 years ago

Thanks for the report!

@noname22 do you have any idea on how this WinMMMidiInput.HandleLongData() could fail like this? I will try by myself once I got a working Windows development setup too.

atsushieno commented 5 years ago

What I have figured out so far:

c.f. https://social.msdn.microsoft.com/forums/vstudio/en-US/ede0ba0b-432c-48b7-9d6e-7bba3b4f062e/midiinproc-not-well-documented

holly-hacker commented 5 years ago

I want to mention that I didn't have this when I was using NAudio, so comparing to it may be useful.

noname22 commented 5 years ago

I wouldn't be surprised if we get a MidiInMessage.Close before that message (which we currently ignore).

See here.

If that's the case we should ignore any messages after close.

atsushieno commented 5 years ago

Thanks, but it does not seem to be sent. I tried adding case MidiInMessage.Close in HandleMidiInProc but it does not happen (at least before the crashy message above). Looks like the message size (buffer.Header.BytesRecorded) is 0.

noname22 commented 5 years ago

Thanks, but it does not seem to be sent. I tried adding case MidiInMessage.Close in HandleMidiInProc but it does not happen (at least before the crashy message above). Looks like the message size (buffer.Header.BytesRecorded) is 0.

Ah, crap :(

Is it possible to just skip any zero byte messages?

atsushieno commented 5 years ago

After all there was no any decent solution, so I just added a workaround (skip it) code at 6b197af. I will be pushed to nuget soon.