protected override void DisconnectInternal(bool isNormal)
 {
     if (_outBuffer != null)
     {
         _outBuffer.Dispose();
         _outBuffer = null;
     }
     if (_inDeviceHandle != IntPtr.Zero)
     {
         if (IsConnected)
         {
             NativeMethods.midiInStop(_inDeviceHandle);
         }
         NativeMethods.midiInClose(_inDeviceHandle);
         _inDeviceHandle = IntPtr.Zero;
         _inputClosed.Wait(2500);
     }
     if (_outDeviceHandle != IntPtr.Zero)
     {
         NativeMethods.midiOutClose(_outDeviceHandle);
         _outDeviceHandle = IntPtr.Zero;
         _outputClosed.Wait(2500);
     }
     _inputCallback  = null;
     _outputCallback = null;
     _inDeviceId     = 0;
     _outDeviceId    = 0;
 }
        protected override bool ConnectInternal(bool isNormal)
        {
            int  inDeviceCount = NativeMethods.midiInGetNumDevs();
            uint?inDeviceId    = null;

            for (uint i = 0; i < inDeviceCount; i++)
            {
                var caps = new MIDIINCAPS();
                NativeMethods.midiInGetDevCaps(i, ref caps, MIDIINCAPS.Size);
                if (caps.szPname == Id)
                {
                    inDeviceId = i;
                    break;
                }
            }
            if (inDeviceId == null)
            {
                return(false);
            }

            int  outDeviceCount = NativeMethods.midiOutGetNumDevs();
            uint?outDeviceId    = null;

            for (uint i = 0; i < outDeviceCount; i++)
            {
                var caps = new MIDIOUTCAPS();
                NativeMethods.midiOutGetDevCaps(i, ref caps, MIDIOUTCAPS.Size);
                if (caps.szPname == Id.Replace("MIDIIN", "MIDIOUT"))
                {
                    outDeviceId = i;
                    break;
                }
            }
            if (outDeviceId == null)
            {
                return(false);
            }

            if (NativeMethods.midiInOpen(out var inDeviceHandle, inDeviceId.Value, _inputCallback, 0, 0x00030000) != 0)
            {
                return(false);
            }
            if (NativeMethods.midiOutOpen(out var outDeviceHandle, outDeviceId.Value, _outputCallback, 0, 0x00030000) != 0)
            {
                return(false);
            }
            if (NativeMethods.midiInStart(inDeviceHandle) != 0)
            {
                return(false);
            }

            _outBuffer = new MidiBuffer(outDeviceHandle, SysEx.MaxMessageLength);

            _inDeviceId      = inDeviceId.Value;
            _outDeviceId     = outDeviceId.Value;
            _inDeviceHandle  = inDeviceHandle;
            _outDeviceHandle = outDeviceHandle;
            _inputCallback   = InputEvent;
            _outputCallback  = OutputEvent;

            _inputClosed.Reset();
            _outputClosed.Reset();

            return(true);
        }