lipsync/trunk/Boare.Lib.Media/MidiInDevice.cs

165 lines
6.1 KiB
C#

/*
* MidiInDevice.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.Collections.Generic;
using bocoree;
namespace Boare.Lib.Media {
public delegate void MidiReceivedEventHandler( DateTime time, byte[] data );
public class MidiInDevice : IDisposable {
delegate void MidiInProcDelegate( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 );
private const int CALLBACK_EVENT = 0x50000;
private const int CALLBACK_FUNCTION = 0x30000;
private const int CALLBACK_NULL = 0;
private const int CALLBACK_TASK = 0x20000;
private const int CALLBACK_THREAD = 0x20000;
private const int CALLBACK_TYPEMASK = 0x70000;
private const int CALLBACK_WINDOW = 0x10000;
private volatile MidiInProcDelegate m_delegate;
private IntPtr m_delegate_pointer;
private uint m_hmidiin = 0;
private int m_port_number;
private const int MM_MIM_CLOSE = 0x3c2;
private const int MM_MIM_DATA = 0x3c3;
private const int MM_MIM_ERROR = 0x3c5;
private const int MM_MIM_LONGDATA = 0x3c4;
private const int MM_MIM_LONGERROR = 0x3c6;
private const int MM_MIM_OPEN = 0x3c1;
public event MidiReceivedEventHandler MidiReceived;
public MidiInDevice( int port_number ) {
m_port_number = port_number;
m_delegate = new MidiInProcDelegate( MidiInProc );
m_delegate_pointer = Marshal.GetFunctionPointerForDelegate( m_delegate );
windows.midiInOpen( ref m_hmidiin, port_number, m_delegate_pointer, 0, CALLBACK_FUNCTION );
}
public void Start() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInStart( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Start" );
debug.push_log( " ex=" + ex );
}
}
}
public void Stop() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInReset( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Stop" );
debug.push_log( " ex=" + ex );
}
}
}
public void Close() {
if ( m_hmidiin > 0 ) {
try {
windows.midiInClose( m_hmidiin );
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.Close" );
debug.push_log( " ex=" + ex );
}
}
m_hmidiin = 0;
}
public void Dispose() {
Close();
}
public static int GetNumDevs() {
try {
int i = (int)windows.midiInGetNumDevs();
return i;
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.GetNumDevs" );
debug.push_log( " ex=" + ex );
}
return 0;
}
public static MIDIINCAPS[] GetMidiInDevices() {
List<MIDIINCAPS> ret = new List<MIDIINCAPS>();
uint num = 0;
try {
num = windows.midiInGetNumDevs();
} catch {
num = 0;
}
for ( uint i = 0; i < num; i++ ) {
MIDIINCAPS m = new MIDIINCAPS();
uint r = windows.midiInGetDevCaps( i, ref m, (uint)Marshal.SizeOf( m ) );
ret.Add( m );
}
return ret.ToArray();
}
private void MidiInProc( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 ) {
try {
switch ( wMsg ) {
case MM_MIM_OPEN:
return;
case MM_MIM_CLOSE:
return;
case MM_MIM_DATA:
int receive = dwParam1;
DateTime now = DateTime.Now;
switch ( receive & 0xF0 ) {
case 0x80:
case 0x90:
case 0xa0:
case 0xb0:
case 0xe0:
if ( MidiReceived != null ) {
MidiReceived( now, new byte[] { (byte)(receive & 0xff),
(byte)((receive & 0xffff) >> 8),
(byte)((receive & ((2 << 24) - 1)) >> 16) } );
}
break;
case 0xc0:
case 0xd0:
if ( MidiReceived != null ) {
MidiReceived( now, new byte[] { (byte)( receive & 0xff ),
(byte)((receive & 0xffff) >> 8) } );
}
break;
}
return;
case MM_MIM_LONGDATA:
return;
case MM_MIM_ERROR:
return;
case MM_MIM_LONGERROR:
return;
}
} catch ( Exception ex ) {
debug.push_log( "MidiInDevice.MidiInProc" );
debug.push_log( " ex=" + ex );
}
}
}
}