using System; using System.Runtime.InteropServices; using NAudio.Wave; namespace NAudio.Midi { /// /// Represents a MIDI out device /// public class MidiOut : IDisposable { private IntPtr hMidiOut = IntPtr.Zero; private bool disposed = false; MidiInterop.MidiOutCallback callback; /// /// Gets the number of MIDI devices available in the system /// public static int NumberOfDevices { get { return MidiInterop.midiOutGetNumDevs(); } } /// /// Gets the MIDI Out device info /// public static MidiOutCapabilities DeviceInfo(int midiOutDeviceNumber) { MidiOutCapabilities caps = new MidiOutCapabilities(); int structSize = Marshal.SizeOf(caps); MmException.Try(MidiInterop.midiOutGetDevCaps((IntPtr)midiOutDeviceNumber, out caps, structSize), "midiOutGetDevCaps"); return caps; } /// /// Opens a specified MIDI out device /// /// The device number public MidiOut(int deviceNo) { this.callback = new MidiInterop.MidiOutCallback(Callback); MmException.Try(MidiInterop.midiOutOpen(out hMidiOut, (IntPtr)deviceNo, callback, IntPtr.Zero, MidiInterop.CALLBACK_FUNCTION), "midiOutOpen"); } /// /// Closes this MIDI out device /// public void Close() { Dispose(); } /// /// Closes this MIDI out device /// public void Dispose() { GC.KeepAlive(callback); Dispose(true); GC.SuppressFinalize(this); } /// /// Gets or sets the volume for this MIDI out device /// public int Volume { // TODO: Volume can be accessed by device ID get { int volume = 0; MmException.Try(MidiInterop.midiOutGetVolume(hMidiOut,ref volume),"midiOutGetVolume"); return volume; } set { MmException.Try(MidiInterop.midiOutSetVolume(hMidiOut,value),"midiOutSetVolume"); } } /// /// Resets the MIDI out device /// public void Reset() { MmException.Try(MidiInterop.midiOutReset(hMidiOut),"midiOutReset"); } /// /// Sends a MIDI out message /// /// Message /// Parameter 1 /// Parameter 2 public void SendDriverMessage(int message, int param1, int param2) { MmException.Try(MidiInterop.midiOutMessage(hMidiOut,message,(IntPtr)param1,(IntPtr)param2),"midiOutMessage"); } /// /// Sends a MIDI message to the MIDI out device /// /// The message to send public void Send(int message) { MmException.Try(MidiInterop.midiOutShortMsg(hMidiOut,message),"midiOutShortMsg"); } /// /// Closes the MIDI out device /// /// True if called from Dispose protected virtual void Dispose(bool disposing) { if(!this.disposed) { //if(disposing) Components.Dispose(); MidiInterop.midiOutClose(hMidiOut); } disposed = true; } private void Callback(IntPtr midiInHandle, MidiInterop.MidiOutMessage message, IntPtr userData, IntPtr messageParameter1, IntPtr messageParameter2) { } /// /// Send a long message, for example sysex. /// /// The bytes to send. public void SendBuffer(byte[] byteBuffer) { var header = new MidiInterop.MIDIHDR(); header.lpData = Marshal.AllocHGlobal(byteBuffer.Length); Marshal.Copy(byteBuffer, 0, header.lpData, byteBuffer.Length); header.dwBufferLength = byteBuffer.Length; header.dwBytesRecorded = byteBuffer.Length; int size = Marshal.SizeOf(header); MidiInterop.midiOutPrepareHeader(this.hMidiOut, ref header, size); var errcode = MidiInterop.midiOutLongMsg(this.hMidiOut, ref header, size); if (errcode != MmResult.NoError) { MidiInterop.midiOutUnprepareHeader(this.hMidiOut, ref header, size); } Marshal.FreeHGlobal(header.lpData); } /// /// Cleanup /// ~MidiOut() { System.Diagnostics.Debug.Assert(false); Dispose(false); } } }