/* * 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 ret = new List(); 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 ); } } } }