1
0
mirror of synced 2024-12-20 11:25:55 +01:00
OpenTaiko/FDK19/コード/02.入力/CInput管理.cs
2021-09-21 00:16:38 +02:00

298 lines
8.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using SharpDX.DirectInput;
namespace FDK
{
public class CInput管理 : IDisposable
{
// 定数
public static int n通常音量 = 110;
// プロパティ
public List<IInputDevice> list入力デバイス
{
get;
private set;
}
public IInputDevice Keyboard
{
get
{
if (this._Keyboard != null)
{
return this._Keyboard;
}
foreach (IInputDevice device in this.list入力デバイス)
{
if (device.e入力デバイス種別 == E入力デバイス種別.Keyboard)
{
this._Keyboard = device;
return device;
}
}
return null;
}
}
public IInputDevice Mouse
{
get
{
if (this._Mouse != null)
{
return this._Mouse;
}
foreach (IInputDevice device in this.list入力デバイス)
{
if (device.e入力デバイス種別 == E入力デバイス種別.Mouse)
{
this._Mouse = device;
return device;
}
}
return null;
}
}
// コンストラクタ
public CInput管理(IntPtr hWnd, bool bUseMidiIn = true)
{
CInput管理初期化(hWnd, bUseMidiIn);
}
public void CInput管理初期化(IntPtr hWnd, bool bUseMidiIn)
{
this.directInput = new DirectInput();
// this.timer = new CTimer( CTimer.E種別.MultiMedia );
this.list入力デバイス = new List<IInputDevice>(10);
#region [ Enumerate keyboard/mouse: exception is masked if keyboard/mouse is not connected ]
CInputKeyboard cinputkeyboard = null;
CInputMouse cinputmouse = null;
try
{
cinputkeyboard = new CInputKeyboard(hWnd, directInput);
cinputmouse = new CInputMouse(hWnd, directInput);
}
catch
{
}
if (cinputkeyboard != null)
{
this.list入力デバイス.Add(cinputkeyboard);
}
if (cinputmouse != null)
{
this.list入力デバイス.Add(cinputmouse);
}
#endregion
#region [ Enumerate joypad ]
foreach (DeviceInstance instance in this.directInput.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly))
{
this.list入力デバイス.Add(new CInputJoystick(hWnd, instance, directInput));
}
#endregion
if (bUseMidiIn)
{
this.proc = new CWin32.MidiInProc(this.MidiInCallback);
uint nMidiDevices = CWin32.midiInGetNumDevs();
Trace.TraceInformation("MIDI入力デバイス数: {0}", nMidiDevices);
for (uint i = 0; i < nMidiDevices; i++)
{
CInputMIDI item = new CInputMIDI(i);
CWin32.MIDIINCAPS lpMidiInCaps = new CWin32.MIDIINCAPS();
uint num3 = CWin32.midiInGetDevCaps(i, ref lpMidiInCaps, (uint)Marshal.SizeOf(lpMidiInCaps));
if (num3 != 0)
{
Trace.TraceError("MIDI In: Device{0}: midiInDevCaps(): {1:X2}: ", i, num3);
}
else
{
uint ret = CWin32.midiInOpen(ref item.hMidiIn, i, this.proc, IntPtr.Zero, 0x30000);
Trace.TraceInformation("midiInOpen()==" + ret);
Trace.TraceInformation("item.hMidiIn==" + item.hMidiIn.ToString());
if ((ret == 0) && (item.hMidiIn != IntPtr.Zero))
{
CWin32.midiInStart(item.hMidiIn);
Trace.TraceInformation("MIDI In: [{0}] \"{1}\" の入力受付を開始しました。", i, lpMidiInCaps.szPname);
item.strDeviceName = lpMidiInCaps.szPname;
this.list入力デバイス.Add(item);
continue;
}
}
Trace.TraceError("MIDI In: [{0}] \"{1}\" の入力受付の開始に失敗しました。", i, lpMidiInCaps.szPname);
}
}
else
{
Trace.TraceInformation("DTXVモードのため、MIDI入力は使用しません。");
}
}
// メソッド
public IInputDevice Joystick(int ID)
{
foreach (IInputDevice device in this.list入力デバイス)
{
if ((device.e入力デバイス種別 == E入力デバイス種別.Joystick) && (device.ID == ID))
{
return device;
}
}
return null;
}
public IInputDevice Joystick(string GUID)
{
foreach (IInputDevice device in this.list入力デバイス)
{
if ((device.e入力デバイス種別 == E入力デバイス種別.Joystick) && device.GUID.Equals(GUID))
{
return device;
}
}
return null;
}
public IInputDevice MidiIn(int ID)
{
foreach (IInputDevice device in this.list入力デバイス)
{
if ((device.e入力デバイス種別 == E入力デバイス種別.MidiIn) && (device.ID == ID))
{
return device;
}
}
return null;
}
public void tポーリング(bool bWindowがアクティブ中, bool bバッファ入力を使用する)
{
lock (this.objMidiIn排他用)
{
// foreach( IInputDevice device in this.list入力デバイス )
for (int i = this.list入力デバイス.Count - 1; i >= 0; i--) // #24016 2011.1.6 yyagi: change not to use "foreach" to avoid InvalidOperation exception by Remove().
{
IInputDevice device = this.list入力デバイス[i];
try
{
device.tポーリング(bWindowがアクティブ中, bバッファ入力を使用する);
}
catch (SharpDX.SharpDXException e) // #24016 2011.1.6 yyagi: catch exception for unplugging USB joystick, and remove the device object from the polling items.
{
if (e.ResultCode == ResultCode.OtherApplicationHasPriority)
{
// #xxxxx: 2017.5.9: from: このエラーの時は、何もしない。
}
else
{
// #xxxxx: 2017.5.9: from: その他のエラーの場合は、デバイスが外されたと想定してRemoveする。
this.list入力デバイス.Remove(device);
device.Dispose();
Trace.TraceError("tポーリング時に対象deviceが抜かれており例外発生。同deviceをポーリング対象からRemoveしました。");
}
}
}
}
}
#region [ IDisposableα ]
//-----------------
public void Dispose()
{
this.Dispose(true);
}
public void Dispose(bool disposeManagedObjects)
{
if (!this.bDisposed済み)
{
if (disposeManagedObjects)
{
foreach (IInputDevice device in this.list入力デバイス)
{
CInputMIDI tmidi = device as CInputMIDI;
if (tmidi != null)
{
CWin32.midiInStop(tmidi.hMidiIn);
CWin32.midiInReset(tmidi.hMidiIn);
CWin32.midiInClose(tmidi.hMidiIn);
Trace.TraceInformation("MIDI In: [{0}] を停止しました。", new object[] { tmidi.ID });
}
}
foreach (IInputDevice device2 in this.list入力デバイス)
{
device2.Dispose();
}
lock (this.objMidiIn排他用)
{
this.list入力デバイス.Clear();
}
this.directInput.Dispose();
//if( this.timer != null )
//{
// this.timer.Dispose();
// this.timer = null;
//}
}
this.bDisposed済み = true;
}
}
~CInput管理()
{
this.Dispose(false);
GC.KeepAlive(this);
}
//-----------------
#endregion
// その他
#region [ private ]
//-----------------
private DirectInput directInput;
private IInputDevice _Keyboard;
private IInputDevice _Mouse;
private bool bDisposed済み;
private List<uint> listHMIDIIN = new List<uint>(8);
private object objMidiIn排他用 = new object();
private CWin32.MidiInProc proc;
//private CTimer timer;
private void MidiInCallback(IntPtr hMidiIn, uint wMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2)
{
int p = (int)dwParam1 & 0xF0;
if (wMsg != CWin32.MIM_DATA || (p != 0x80 && p != 0x90 && p != 0xB0))
return;
long time = CSound管理.rc演奏用タイマ.nシステム時刻; // lock前に取得。演奏用タイマと同じタイマを使うことで、BGMと譜面、入力ずれを防ぐ。
lock (this.objMidiIn排他用)
{
if ((this.list入力デバイス != null) && (this.list入力デバイス.Count != 0))
{
foreach (IInputDevice device in this.list入力デバイス)
{
CInputMIDI tmidi = device as CInputMIDI;
if ((tmidi != null) && (tmidi.hMidiIn == hMidiIn))
{
tmidi.tメッセージからMIDI信号のみ受信(wMsg, dwInstance, dwParam1, dwParam2, time);
break;
}
}
}
}
}
//-----------------
#endregion
}
}