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);
}
}
}