2024-06-07 00:47:07 +02:00

163 lines
5.1 KiB
C#

using System;
using System.Runtime.InteropServices;
using NAudio.Wave;
namespace NAudio.Midi
{
/// <summary>
/// Represents a MIDI out device
/// </summary>
public class MidiOut : IDisposable
{
private IntPtr hMidiOut = IntPtr.Zero;
private bool disposed = false;
MidiInterop.MidiOutCallback callback;
/// <summary>
/// Gets the number of MIDI devices available in the system
/// </summary>
public static int NumberOfDevices
{
get
{
return MidiInterop.midiOutGetNumDevs();
}
}
/// <summary>
/// Gets the MIDI Out device info
/// </summary>
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;
}
/// <summary>
/// Opens a specified MIDI out device
/// </summary>
/// <param name="deviceNo">The device number</param>
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");
}
/// <summary>
/// Closes this MIDI out device
/// </summary>
public void Close()
{
Dispose();
}
/// <summary>
/// Closes this MIDI out device
/// </summary>
public void Dispose()
{
GC.KeepAlive(callback);
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Gets or sets the volume for this MIDI out device
/// </summary>
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");
}
}
/// <summary>
/// Resets the MIDI out device
/// </summary>
public void Reset()
{
MmException.Try(MidiInterop.midiOutReset(hMidiOut),"midiOutReset");
}
/// <summary>
/// Sends a MIDI out message
/// </summary>
/// <param name="message">Message</param>
/// <param name="param1">Parameter 1</param>
/// <param name="param2">Parameter 2</param>
public void SendDriverMessage(int message, int param1, int param2)
{
MmException.Try(MidiInterop.midiOutMessage(hMidiOut,message,(IntPtr)param1,(IntPtr)param2),"midiOutMessage");
}
/// <summary>
/// Sends a MIDI message to the MIDI out device
/// </summary>
/// <param name="message">The message to send</param>
public void Send(int message)
{
MmException.Try(MidiInterop.midiOutShortMsg(hMidiOut,message),"midiOutShortMsg");
}
/// <summary>
/// Closes the MIDI out device
/// </summary>
/// <param name="disposing">True if called from Dispose</param>
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)
{
}
/// <summary>
/// Send a long message, for example sysex.
/// </summary>
/// <param name="byteBuffer">The bytes to send.</param>
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);
}
/// <summary>
/// Cleanup
/// </summary>
~MidiOut()
{
System.Diagnostics.Debug.Assert(false);
Dispose(false);
}
}
}