void SendLongMsg(int systemHandle, byte[] data) { if (data.Length > (64 * 1024)) { throw new ArgumentOutOfRangeException(); } //----------// MidiHdr int hdrSize = Marshal.SizeOf(typeof(MidiHdr)); byte[] hdrReserved = new byte[8]; MidiHdr hdr = new MidiHdr(); GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); GCHandle revHandle = GCHandle.Alloc(hdrReserved, GCHandleType.Pinned); //----------// MidiHdr hdr.lpData = handle.AddrOfPinnedObject(); hdr.dwBufferLength = (uint)data.Length; hdr.dwFlags = 0; //----------// midiOutPrepareHeader(systemHandle, ref hdr, hdrSize); while ((hdr.dwFlags & MidiHdrFlag.MHDR_PREPARED) != MidiHdrFlag.MHDR_PREPARED) { Thread.Sleep(1); } midiOutLongMsg(systemHandle, ref hdr, hdrSize); while ((hdr.dwFlags & MidiHdrFlag.MHDR_DONE) != MidiHdrFlag.MHDR_DONE) { Thread.Sleep(1); } midiOutUnprepareHeader(systemHandle, ref hdr, hdrSize); //----------// GCHandle handle.Free(); revHandle.Free(); //----------// }
internal static ushort Midi_Send_String(byte[] data, ushort len) { if (s_midi == IntPtr.Zero) { return(len); } var header = new MidiHdr(); var hdrSize = Marshal.SizeOf(typeof(MidiHdr)); var prepared = false; var ptr = IntPtr.Zero; try { header.Data = Marshal.AllocHGlobal(len); header.BufferLength = len; Marshal.Copy(data, 0, header.Data, header.BufferLength); //TODO: Use Unsafe.CopyBlock? ptr = Marshal.AllocHGlobal(hdrSize); Marshal.StructureToPtr(header, ptr, false); if (midiOutPrepareHeader(s_midi, ptr, hdrSize) != MMSYSERR_NOERROR) { Trace.WriteLine("ERROR: midiOutPrepareHeader() failed"); } else { prepared = true; Debug.Assert(midiOutLongMsg(s_midi, ptr, hdrSize) == MMSYSERR_NOERROR); } } finally { if (prepared) { if (midiOutUnprepareHeader(s_midi, ptr, hdrSize) != MMSYSERR_NOERROR) { Trace.WriteLine("ERROR: midiOutUnprepareHeader() failed"); } } if (header.Data != IntPtr.Zero) { Marshal.FreeHGlobal(header.Data); } if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } } return(len); }
private void MidiInCallback(int hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2) { switch (wMsg) { case MM_OPEN: break; case MM_CLOSE: break; case MM_LONGDATA: MidiHdr midiHeader = (MidiHdr)Marshal.PtrToStructure((IntPtr)dwParam1, typeof(MidiHdr)); for (int i = 0; midiHeader.bytesRecorded-- > 0; i++) { byte bteRead = Marshal.ReadByte(midiHeader.data, i); switch (bteRead) { case 0xF0: case 0xF7: if (_buffer.Length > 0) { if (_remoteButtonHandler != null) { _remoteButtonHandler(Name, _buffer.ToString()); } _buffer.Remove(0, _buffer.Length); } break; default: _buffer.Append(bteRead.ToString("x2")); break; } } midiHeader.bytesRecorded = 0; if (!_stopping) { midiInAddBuffer(hMidiIn, dwParam1, Marshal.SizeOf(typeof(MidiHdr))); } break; default: break; } }
/// <summary> /// Start the IR Server plugin. /// </summary> public override void Start() { uint error; LoadSettings(); _stopping = false; _buffer = new StringBuilder(BufferLength); //MidiInProc _midiCallback = MidiInCallback; _midiHeader = new MidiHdr(); _midiHeader.data = Marshal.AllocHGlobal(BufferLength); _midiHeader.bufferLength = BufferLength; _midiHeader.flags = 0; error = midiInOpen(ref _midiInHandle, _midiIndex, _midiCallback, 0, CALLBACK_FUNCTION); if (error == MMSYSERR_NOERROR) { error = midiInPrepareHeader(_midiInHandle, ref _midiHeader, Marshal.SizeOf(typeof(MidiHdr))); if (error == MMSYSERR_NOERROR) { IntPtr iptMIDIHdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MidiHdr))); Marshal.StructureToPtr(_midiHeader, iptMIDIHdrPtr, true); error = midiInAddBuffer(_midiInHandle, (int)iptMIDIHdrPtr, Marshal.SizeOf(typeof(MidiHdr))); if (error == MMSYSERR_NOERROR) { error = midiInStart(_midiInHandle); } } } }
public static class MidiTest { // version 3 - x68/x64 32/64-bit compatible public static void Test() { int moID = 0; // midi out device/port ID IntPtr moHdl = IntPtr.Zero; #if !true // SysEx via midiOutLongMsg works Chk(WinMM.midiOutOpen(out moHdl, moID, null, 0, 0)); // open midi out in non-stream mode #else // SysEx via midiOutLongMsg fails IntPtr instance = IntPtr.Zero; Chk(WinMM.midiStreamOpen(out moHdl, ref moID, 1, null, instance, 0)); // open midi out in stream mode #endif byte[] sx = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 }; // GM On sysex int shdr = Marshal.SizeOf(typeof(MidiHdr)); // hdr size IntPtr x = Marshal.OffsetOf(typeof(MidiHdr), "data"); // ptr; size: 4/8, offset: 0 x = Marshal.OffsetOf(typeof(MidiHdr), "bufferLength"); // int; size: 4 , offset: 4/8 x = Marshal.OffsetOf(typeof(MidiHdr), "bytesRecorded"); // int; size: 4 , offset: 8/12 x = Marshal.OffsetOf(typeof(MidiHdr), "user"); // ptr; size: 4/8, offset: 12/16 x = Marshal.OffsetOf(typeof(MidiHdr), "flags"); // int; size: 4 , offset: 16/24; followed by 4 byte padding x = Marshal.OffsetOf(typeof(MidiHdr), "next"); // ptr; size: 4/8, offset: 20/32 x = Marshal.OffsetOf(typeof(MidiHdr), "reserved"); // ptr; size: 4/8, offset: 24/40 x = Marshal.OffsetOf(typeof(MidiHdr), "offset"); // int; size: 4 , offset: 28/48; followed by 4 byte padding x = Marshal.OffsetOf(typeof(MidiHdr), "reservedArray"); // ptr; size: 4/8 x 8 = 32/64, offset: 32/56 // total size: 64/120 var mhdr = new MidiHdr(); // allocate managed hdr mhdr.bufferLength = mhdr.bytesRecorded = sx.Length; // length of message bytes mhdr.data = Marshal.AllocHGlobal(mhdr.bufferLength); // allocate native message bytes Marshal.Copy(sx, 0, mhdr.data, mhdr.bufferLength); // copy message bytes from managed to native memory IntPtr nhdr = Marshal.AllocHGlobal(shdr); // allocate native hdr Marshal.StructureToPtr(mhdr, nhdr, false); // copy managed hdr to native hdr Chk(WinMM.midiOutPrepareHeader(moHdl, nhdr, shdr)); // prepare native hdr int r = WinMM.midiOutLongMsg(moHdl, nhdr, shdr); // send native message bytes Chk(r); // send native message bytes } // Test
private static extern uint midiInUnprepareHeader(int hMidiIn, ref MidiHdr lpMidiInHdr, int uSize);
/// <summary> /// Start the IR Server plugin. /// </summary> public override void Start() { uint error; LoadSettings(); _stopping = false; _buffer = new StringBuilder(BufferLength); //MidiInProc _midiCallback = MidiInCallback; _midiHeader = new MidiHdr(); _midiHeader.data = Marshal.AllocHGlobal(BufferLength); _midiHeader.bufferLength = BufferLength; _midiHeader.flags = 0; error = midiInOpen(ref _midiInHandle, _midiIndex, _midiCallback, 0, CALLBACK_FUNCTION); if (error == MMSYSERR_NOERROR) { error = midiInPrepareHeader(_midiInHandle, ref _midiHeader, Marshal.SizeOf(typeof (MidiHdr))); if (error == MMSYSERR_NOERROR) { IntPtr iptMIDIHdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (MidiHdr))); Marshal.StructureToPtr(_midiHeader, iptMIDIHdrPtr, true); error = midiInAddBuffer(_midiInHandle, (int) iptMIDIHdrPtr, Marshal.SizeOf(typeof (MidiHdr))); if (error == MMSYSERR_NOERROR) error = midiInStart(_midiInHandle); } } }
static extern int midiOutUnprepareHeader(int hMidiOut, ref MidiHdr lpMidiOutHdr, int uSize);
static extern int midiOutLongMsg(int hMidiOut, ref MidiHdr lpMidiOutHdr, int uSize);
public static extern MMRESULT midiOutPrepareHeader(IntPtr hmo, MidiHdr lpMidiOutHdr, uint cbMidiOutHdr);