2009-07-30 08:02:59 -07:00
|
|
|
|
/*
|
|
|
|
|
* MidiOutDevice.cs
|
|
|
|
|
* Copyright (c) 2009 kbinani
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Boare.Lib.Media.
|
|
|
|
|
*
|
|
|
|
|
* Boare.Lib.Media is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the BSD License.
|
|
|
|
|
*
|
|
|
|
|
* Boare.Lib.Media 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.
|
|
|
|
|
*/
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
using bocoree;
|
|
|
|
|
|
|
|
|
|
namespace Boare.Lib.Media {
|
|
|
|
|
|
|
|
|
|
public unsafe class MidiOutDevice {
|
|
|
|
|
private IntPtr m_handle;
|
|
|
|
|
private uint m_device_id;
|
|
|
|
|
|
|
|
|
|
public MidiOutDevice( uint device_id ) {
|
|
|
|
|
m_device_id = device_id;
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutOpen( ref m_handle, m_device_id, null, 0, win32.CALLBACK_NULL );
|
2009-07-30 08:02:59 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Close() {
|
|
|
|
|
if ( !m_handle.Equals( IntPtr.Zero ) ) {
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutClose( m_handle );
|
2009-07-30 08:02:59 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ProgramChange( byte channel, byte program ) {
|
|
|
|
|
SendShort( new byte[] { (byte)(0xc0 | (channel & 0x0f)) , program, 0x0 } );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Play( byte channel, byte note, byte velocity ) {
|
|
|
|
|
SendShort( new byte[] { (byte)(0x90 | (channel & 0x0f)), note, velocity } );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SendData( byte[] data ) {
|
|
|
|
|
if ( 0 < data.Length && data.Length <= 4 ) {
|
|
|
|
|
SendShort( data );
|
|
|
|
|
} else {
|
|
|
|
|
SendLong( data );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SendShort( byte[] data ) {
|
|
|
|
|
uint message = 0;
|
|
|
|
|
for ( int i = 0; i < data.Length; i++ ) {
|
|
|
|
|
message |= ((uint)data[i]) << (i * 8);
|
|
|
|
|
}
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutShortMsg( m_handle, message );
|
2009-07-30 08:02:59 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SendLong( byte[] data ) {
|
|
|
|
|
MIDIHDR hdr = new MIDIHDR();
|
|
|
|
|
GCHandle dataHandle = GCHandle.Alloc( data, GCHandleType.Pinned );
|
|
|
|
|
uint size = (uint)sizeof( MIDIHDR );
|
|
|
|
|
try {
|
|
|
|
|
hdr.lpData = (byte*)dataHandle.AddrOfPinnedObject().ToPointer();
|
|
|
|
|
hdr.dwBufferLength = (uint)data.Length;
|
|
|
|
|
hdr.dwFlags = 0;
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutPrepareHeader( m_handle, ref hdr, size );
|
|
|
|
|
while ( (hdr.dwFlags & win32.WHDR_PREPARED) != win32.WHDR_PREPARED ) {
|
2009-07-30 08:02:59 -07:00
|
|
|
|
Application.DoEvents();
|
|
|
|
|
}
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutLongMsg( m_handle, ref hdr, size );
|
|
|
|
|
while ( (hdr.dwFlags & win32.WHDR_DONE) != win32.WHDR_DONE ) {
|
2009-07-30 08:02:59 -07:00
|
|
|
|
Application.DoEvents();
|
|
|
|
|
}
|
2010-03-16 20:14:08 -07:00
|
|
|
|
win32.midiOutUnprepareHeader( m_handle, ref hdr, size );
|
2009-07-30 08:02:59 -07:00
|
|
|
|
} finally {
|
|
|
|
|
dataHandle.Free();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|