public string Open() { // Open the port var st = AlsaNativeMethods.Snd_rawmidi_open_input( ref handle, IntPtr.Zero, Device, AlsaNativeMethods.EMode.SND_RAWMIDI_NONBLOCK); return(AlsaUtils.StrError(st)); }
public string Start() { int st = (int)AlsaNativeMethods.Snd_rawmidi_read(handle, null, 0); if (st == 0) { stop = false; readThread = new Thread(ReadThreadStart); readThread.Start(); } return(AlsaUtils.StrError(st)); }
public string Close() { int st = 0; if (handle != IntPtr.Zero) { st = AlsaNativeMethods.Snd_rawmidi_close(handle); handle = IntPtr.Zero; } return(AlsaUtils.StrError(st)); }
// Send a message public string Send(MidiMessage m) { byte[] data = m.GetAsByteArray(); // Meta messages are not sent over the wire if (data == null) { return(null); } ulong size = (ulong)data.Length; long st = AlsaNativeMethods.Snd_rawmidi_write(handle, data, size); return(AlsaUtils.StrError((int)st)); }
private void ReadThreadStart() { byte[] buf = new byte[512]; byte[] overflowBuf = null; // Compute number of pollfd structures required to poll int numPollStructs = AlsaNativeMethods.Snd_rawmidi_poll_descriptors_count(handle); // Allocate space for the poll structures IntPtr pollAreaPtr = Marshal.AllocHGlobal(numPollStructs * AlsaNativeMethods.POLLFDSZ); int st = AlsaNativeMethods.Snd_rawmidi_poll_descriptors(handle, pollAreaPtr, (uint)numPollStructs); while (!stop) { st = AlsaNativeMethods.Poll(pollAreaPtr, numPollStructs, 200); if (st < 0) { var errno = Marshal.GetLastWin32Error(); if (errno == 4 /* EINTR */) { continue; } Console.WriteLine("MidiIn: Cannot poll - errno = " + errno); break; } if (st == 0) { continue; } // We got something - scan the poll struct ushort revent = 0; st = AlsaNativeMethods.Snd_rawmidi_poll_descriptors_revents( handle, pollAreaPtr, (uint)numPollStructs, ref revent); if (st < 0) { Console.WriteLine("MidiIn: Cannot parse poll - " + AlsaUtils.StrError(st)); break; } AlsaNativeMethods.EPoll evt = (AlsaNativeMethods.EPoll)revent; if (evt.HasFlag(AlsaNativeMethods.EPoll.POLLERR) || evt.HasFlag(AlsaNativeMethods.EPoll.POLLHUP)) { break; } if (evt.HasFlag(AlsaNativeMethods.EPoll.POLLIN)) { // We have something to read - read it int nRead = (int)AlsaNativeMethods.Snd_rawmidi_read(handle, buf, (uint)buf.Length); if (nRead < 0) { int errno = Marshal.GetLastWin32Error(); if (errno == 4 /* EINTR */) { continue; } Console.WriteLine("MidiIn: Cannot parse poll - " + AlsaUtils.StrError(st)); break; } // Combine with overflow buffer if we had an overflow last time if (overflowBuf != null) { var newBuf = new byte[buf.Length + overflowBuf.Length]; Array.Copy(overflowBuf, 0, newBuf, 0, overflowBuf.Length); Array.Copy(buf, 0, newBuf, overflowBuf.Length, buf.Length); buf = newBuf; overflowBuf = null; } // Translate the input to midi message int nParsed = 0; while (true) { st = ParseBuffer(buf, nParsed, nRead, out MidiMessage midiMessage); if (st < 0) { // buffer contains an incomplete message overflowBuf = buf; buf = new byte[overflowBuf.Length]; } else if (st == 0) { // Message not supported - drop everything. break; } else // st > 0 { // Send message var midiEvent = new MidiEvent(midiMessage, 0); var midiEventArg = new WindowsMultiMedia.WindowsMidiEventArgs(midiEvent, IntPtr.Zero, IntPtr.Zero); MidiInputReceived?.Invoke(this, midiEventArg); // Update counters nParsed += st; nRead -= st; if (nRead <= 0) { // Normal end break; } } } } } Marshal.FreeHGlobal(pollAreaPtr); }
public string Reset() { int st = AlsaNativeMethods.Snd_rawmidi_drop(handle); return(AlsaUtils.StrError(st)); }