/// <summary> /// Manages system exclusive messages received by the input device. /// </summary> /// <param name="param1"> /// Integer pointer to the header containing the received system /// exclusive message. /// </param> /// <param name="timeStamp"> /// Number of milliseconds that have passed since the input device /// began recording. /// </param> private void ManageSysExMessage(int param1, int timeStamp) { // Get pointer to header. IntPtr ptrHeader = new IntPtr(param1); // If anyone is listening for system exclusive messages. if (SysExReceived != null) { // Imprint raw pointer on to structure. MidiHeader header = (MidiHeader)Marshal.PtrToStructure(ptrHeader, typeof(MidiHeader)); // Dispatches system exclusive messages. DispatchSysExMessage(header, timeStamp); } // Unprepare header. ThrowOnError(midiInUnprepareHeader(handle, ptrHeader, Marshal.SizeOf(typeof(MidiHeader)))); // Prepare header to be used again. ThrowOnError(midiInPrepareHeader(handle, ptrHeader, Marshal.SizeOf(typeof(MidiHeader)))); // Add header back to buffer. ThrowOnError(midiInAddBuffer(handle, ptrHeader, Marshal.SizeOf(typeof(MidiHeader)))); }
/// <summary> /// Sends system exclusive messages. /// </summary> /// <param name="message"> /// The system exclusive message to send. /// </param> public void Send(SysExMessage message) { // If the device is open. if (IsOpen()) { // Create header. MidiHeader header = new MidiHeader(); // System exclusive message data. string msg = message.Message; // // Initialize header. // header.data = Marshal.StringToHGlobalAnsi(msg); header.bufferLength = msg.Length; header.flags = 0; // Prepare header. ThrowOnError(midiOutPrepareHeader(handle, ref header, Marshal.SizeOf(header))); // Place header in queue to be retrieved later. syncHeaderQueue.Enqueue(header); // Send message. ThrowOnError(midiOutLongMsg(handle, ref header, Marshal.SizeOf(header))); } }
/// <summary> /// Empties header queue. /// </summary> private void EmptyHeaderQueue() { IEnumerator en = syncHeaderQueue.GetEnumerator(); // While there are still headers in the queue. while (en.MoveNext()) { // Get header. MidiHeader header = (MidiHeader)en.Current; // Unprepare header. ThrowOnError(midiOutUnprepareHeader(handle, ref header, Marshal.SizeOf(header))); // Free memory allocated for the system exclusive data. Marshal.FreeHGlobal(header.data); } // Clear queue. syncHeaderQueue.Clear(); }
/// <summary> /// Handles triggering the system exclusive message received event. /// </summary> /// <param name="header"> /// Midi header containing the system exclusive message. /// </param> /// <param name="timeStamp"> /// Number of milliseconds that have passed since the input device /// began recording. /// </param> private void DispatchSysExMessage(MidiHeader header, int timeStamp) { // Create array for holding system exclusive data. byte[] data = new byte[header.bytesRecorded - 1]; // Get status byte. byte status = Marshal.ReadByte(header.data); // Copy system exclusive data into array (status byte is // excluded). for (int i = 1; i < header.bytesRecorded; i++) { data[i - 1] = Marshal.ReadByte(header.data, i); } // Create message. SysExMessage msg = new SysExMessage((SysExType)status, data); // Raise event. SysExReceived(this, new SysExEventArgs(msg, timeStamp)); }
/// <summary> /// Thread method for managing headers. /// </summary> private void ManageHeaders() { // While the device is open. while (IsOpen()) { // Wait to be signalled when a header had finished being used. resetEvent.WaitOne(); // While there are still headers in the queue. while (syncHeaderQueue.Count > 0) { // Get header from the front of the queue. MidiHeader header = (MidiHeader)syncHeaderQueue.Dequeue(); // Unprepare header. ThrowOnError(midiOutUnprepareHeader(handle, ref header, Marshal.SizeOf(header))); // Free memory allocated for the system exclusive data. Marshal.FreeHGlobal(header.data); } } }
private static extern int midiOutLongMsg(int handle, ref MidiHeader midiHeader, int sizeOfmidiHeader);
private static extern int midiOutUnprepareHeader(int handle, ref MidiHeader midiHeader, int sizeOfmidiHeader);
/// <summary> /// Handles triggering the system exclusive message received event. /// </summary> /// <param name="header"> /// Midi header containing the system exclusive message. /// </param> /// <param name="timeStamp"> /// Number of milliseconds that have passed since the input device /// began recording. /// </param> private void DispatchSysExMessage(MidiHeader header, int timeStamp) { // Create array for holding system exclusive data. byte[] data = new byte[header.bytesRecorded - 1]; // Get status byte. byte status = Marshal.ReadByte(header.data); // Copy system exclusive data into array (status byte is // excluded). for(int i = 1; i < header.bytesRecorded; i++) { data[i - 1] = Marshal.ReadByte(header.data, i); } // Create message. SysExMessage msg = new SysExMessage((SysExType)status, data); // Raise event. SysExReceived(this, new SysExEventArgs(msg, timeStamp)); }
/// <summary> /// Sends system exclusive messages. /// </summary> /// <param name="message"> /// The system exclusive message to send. /// </param> public void Send(SysExMessage message) { // If the device is open. if(IsOpen()) { // Create header. MidiHeader header = new MidiHeader(); // System exclusive message data. string msg = message.Message; // // Initialize header. // header.data = Marshal.StringToHGlobalAnsi(msg); header.bufferLength = msg.Length; header.flags = 0; // Prepare header. ThrowOnError(midiOutPrepareHeader(handle, ref header, Marshal.SizeOf(header))); // Place header in queue to be retrieved later. syncHeaderQueue.Enqueue(header); // Send message. ThrowOnError(midiOutLongMsg(handle, ref header, Marshal.SizeOf(header))); } }