context: //=================================================================
  // midi.cs
  //=================================================================
  // PowerSDR is a C# implementation of a Software Defined Radio.
  // Copyright (C) 2004-2009  FlexRadio Systems
  //
  // This program is free software; you can redistribute it and/or
  // modify it under the terms of the GNU General Public License
  // as published by the Free Software Foundation; either version 2
  // of the License, or (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program; if not, write to the Free Software
  // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  //
  // You may contact us via email at: sales@flex-radio.com.
  // Paper mail may be sent to: 
  //    FlexRadio Systems
  //    8900 Marybank Dr.
  //    Austin, TX 78750
  //    USA
  //=================================================================
  
  using System;
  using System.Diagnostics;
  using System.Text;
  using System.Runtime.InteropServices;
  using System.Collections;
  using System.Threading;
  
  namespace PowerSDR
  {
  	/// <summary>
  	/// Summary description for midi.
  	/// </summary>
  	unsafe public class Midi
  	{
          #region Enums
  
          private enum Command
          {
              NoteOn = 0x90,
              NoteOff = 0x80,
              Aftertouch0 = 0xA0,
              Aftertouch1 = 0xA1,
              Controller = 0xB0,
              PolyPressure = 0xA0,
              ProgramChange = 0xC0,
              ChannelPressure = 0xD0,
              PitchWheel = 0xE0
          }
  
          private enum Controller
          {
              HoldPedal1 = 64,
              HoldPedal2 = 69,
          }
  
          private enum Note
          {
              Mox = 0,
              PAADC = 1,
              Dot = 61,
              Dash = 63,
              MicDown = 66,
              MicUp = 68,
              MicFast = 70,
          }
  
          #endregion
  
         // private DJConsole djConsole;
          public const int CALLBACK_FUNCTION = 0x00030000;
  		public const int MIM_OPEN = 0x3C1;
  		public const int MIM_CLOSE = 0x3C2;
  		public const int MIM_DATA = 0x3C3;
  		public const int MIM_LONGDATA = 0x3C4;
  
          private static MidiInCallback callback;
          private static bool resetting = false;
          private static int midi_in_handle;
          private static int midi_out_handle;
          private static object in_lock_obj = new Object();
          private static object out_lock_obj = new Object();
  
          public static int DeviceInCount
          {
              get
              {
                  return MidiInGetNumDevs();
              }
          }
  
          public static int DeviceOutCount
          {
              get
              {
                  return MidiOutGetNumDevs();
              }
          }
          
          public static bool Present()
  		{
  			int num_in = MidiInGetNumDevs();
  			for(int i=0; i<num_in; i++)
  			{
  				
  				string s = MidiInGetName(i);
  				//if(s == "FLEX 5000" || s == "FLEX-5000 Midi" || s == "FlexRadio Flex-5000" || s == "FlexRadio Flex-5000 MIDI")
  				if(s.IndexOf("FLEX") >= 0 || s.IndexOf("Flex") >= 0)
  				{
  					goto test_out;
  				}
  			}
  
  			return false;
  
  			test_out:
  				int num_out = MidiOutGetNumDevs();
  			for(int i=0; i<num_out; i++)
  			{
  				string s = MidiOutGetName(i);
  				//if(s == "FLEX 5000" || s == "2- FLEX-5000 Midi" || s == "FlexRadio Flex-5000" || s == "2- FlexRadio Flex-5000 MIDI")
  				if(s.IndexOf("FLEX") >= 0 || s.IndexOf("Flex") >= 0)
  				{
  					return true;
  				}
  			}
  			return false;
  		}
  
  		public static bool Open()
  		{
  			FillTables();
  			//if(!OpenMidiIn()) return false;
  			//if(!OpenMidiOut()) return false;
  			return true;
  		}
  
  		public static bool OpenMidiIn(int deviceID)
  		{
  			callback = new MidiInCallback(InCallback);
  			int result = MidiInOpen(ref midi_in_handle, deviceID, callback, 0, Midi.CALLBACK_FUNCTION);
  			if(result != 0)
  			{
  				StringBuilder error_text = new StringBuilder(64);
  				MidiInGetErrorText(result, error_text, 64);
  				Debug.WriteLine("MidiInOpen Error: "+error_text);
  				//MessageBox.Show("Error opening Midi In device");
  				return false;
  			}
  
  			for(int i=0; i<3; i++)
  			{
  				result = AddSysExBuffer(midi_in_handle);
  				if(result != 0)
  				{
  					StringBuilder error_text = new StringBuilder(64);
  					MidiInGetErrorText(result, error_text, 64);
  					Debug.WriteLine("AddSysExBuffer Error: "+error_text);
  					//MessageBox.Show("Error adding Midi In device SysEx Buffer");
  					return false;
  				}
  			}
  
  			result = MidiInStart(midi_in_handle);
  			if(result != 0)
  			{
  				StringBuilder error_text = new StringBuilder(64);
  				MidiInGetErrorText(result, error_text, 64);
  				Debug.WriteLine("MidiInStart Error: "+error_text);
  				//MessageBox.Show("Error starting Midi In device");
  				return false;
  			}
  
  			return true;
  		}
  
          public static bool OpenMidiOut(int deviceID)
  		{
  			int result = MidiOutOpen(ref midi_out_handle, deviceID, IntPtr.Zero, 0, 0);
  			if(result != 0)
  			{
  				StringBuilder error_text = new StringBuilder(64);
  				MidiInGetErrorText(result, error_text, 64);
  				Debug.WriteLine("MidiOutOpen Error: "+error_text);
  				//MessageBox.Show("Error Opening Midi Out device");
  				return false;
  			}
  			return true;
  		}
  
  		public static void Close()
  		{
  			CloseMidiIn();
  			CloseMidiOut();
  		}
  
  		private static void CloseMidiIn()
  		{
  			if(midi_in_handle != 0)
  			{
  				MidiInStop(midi_in_handle);
  				resetting = true;
  				MidiInReset(midi_in_handle);
  				MidiInClose(midi_in_handle);
  				midi_in_handle = 0;
  				resetting = false;
  			}
  		}
  
  		private static void CloseMidiOut()
  		{
  			if(midi_out_handle != 0)
  			{
  				MidiOutClose(midi_out_handle);
  			}
  		}
  
  		// F0 <3 mfc> <2 msgID> <2 protocolID> <4 opcode> <4 data1> <4 data2> F7
  		private static ushort msgID = 0;
  		public static void SendSetMessage(FWC.Opcode opcode, uint data1, uint data2)
  		{
  			ushort id = msgID++;
  			byte[] msg = new byte[37];
  			msg[0] = 0xF0; // start byte
  			msg[1] = 0x00; // mfc highest byte
  			msg[2] = 0x00; // mfc high byte
  			msg[3] = 0x41;	// mfc low byte
  			
  			byte[] guts = new byte[16];
  			byte[] temp = new byte[32];
  
  			byte[] temp2 = BitConverter.GetBytes(id);
  			temp2.CopyTo(guts, 0);
  
  			temp2 = BitConverter.GetBytes((uint)opcode);
  			temp2.CopyTo(guts, 4);
  
  			temp2 = BitConverter.GetBytes(data1);
  			temp2.CopyTo(guts, 8);
  
  			temp2 = BitConverter.GetBytes(data2);
  			temp2.CopyTo(guts, 12);
  
  			EncodeBytes(temp, guts);
  
  			temp.CopyTo(msg, 4);
  			//DebugByte(guts);
  			
  			/*DecodeBytes(guts, temp);
  			DebugByte(guts);*/
  
  			msg[36] = 0xF7;
  			//DebugByte(msg);
  			
  			lock(out_lock_obj)
  				if(SendLongMessage(midi_out_handle, msg) != 0)
  					Debug.WriteLine("Error in SendLongMessage");
  		}
  
  		public static void SendSetMessage(FWC.Opcode opcode, float data1, uint data2)
  		{
  			ushort id = msgID++;
  			byte[] msg = new byte[37];
  			msg[0] = 0xF0; // start byte
  			msg[1] = 0x00; // mfc highest byte
  			msg[2] = 0x00; // mfc high byte
  			msg[3] = 0x41;	// mfc low byte
  			
  			byte[] guts = new byte[16];
  			byte[] temp = new byte[32];
  
  			byte[] temp2 = BitConverter.GetBytes(id);
  			temp2.CopyTo(guts, 0);
  
  			temp2 = BitConverter.GetBytes((uint)opcode);
  			temp2.CopyTo(guts, 4);
  
  			temp2 = BitConverter.GetBytes(data1);
  			temp2.CopyTo(guts, 8);
  
  			temp2 = BitConverter.GetBytes(data2);
  			temp2.CopyTo(guts, 12);
  
  			EncodeBytes(temp, guts);
  
  			temp.CopyTo(msg, 4);
  			//DebugByte(guts);
  			
  			/*DecodeBytes(guts, temp);
  			DebugByte(guts);*/
  
  			msg[36] = 0xF7;
  			//DebugByte(msg);
  			
  			lock(out_lock_obj)
  				if(SendLongMessage(midi_out_handle, msg) != 0)
  					Debug.WriteLine("Error in SendLongMessage");
  		}
  
  		public static void SendSetMessage(FWC.Opcode opcode, uint data1, float data2)
  		{
  			ushort id = msgID++;
  			byte[] msg = new byte[37];
  			msg[0] = 0xF0; // start byte
  			msg[1] = 0x00; // mfc highest byte
  			msg[2] = 0x00; // mfc high byte
  			msg[3] = 0x41;	// mfc low byte
  			
  			byte[] guts = new byte[16];
  			byte[] temp = new byte[32];
  
  			byte[] temp2 = BitConverter.GetBytes(id);
  			temp2.CopyTo(guts, 0);
  
  			temp2 = BitConverter.GetBytes((uint)opcode);
  			temp2.CopyTo(guts, 4);
  
  			temp2 = BitConverter.GetBytes(data1);
  			temp2.CopyTo(guts, 8);
  
  
gt: 			temp2 = BitConverter.GetBytes(data2);