OSDN Git Service

DirectInputのポーリング時、バックグラウンドに移るなどの要因で OtherApplicationHasPriority エラー「以外」が発生した場合にのみデバイ...
[dtxmania/dtxmania.git] / FDK17プロジェクト / コード / 02.入力 / CInput管理.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Text;\r
4 using System.Diagnostics;\r
5 using System.Runtime.InteropServices;\r
6 using SharpDX.DirectInput;\r
7 \r
8 namespace FDK\r
9 {\r
10         public class CInput管理 : IDisposable\r
11         {\r
12                 // 定数\r
13 \r
14                 public static int n通常音量 = 110;\r
15 \r
16 \r
17                 // プロパティ\r
18 \r
19                 public List<IInputDevice> list入力デバイス \r
20                 {\r
21                         get;\r
22                         private set;\r
23                 }\r
24                 public IInputDevice Keyboard\r
25                 {\r
26                         get\r
27                         {\r
28                                 if( this._Keyboard != null )\r
29                                 {\r
30                                         return this._Keyboard;\r
31                                 }\r
32                                 foreach( IInputDevice device in this.list入力デバイス )\r
33                                 {\r
34                                         if( device.e入力デバイス種別 == E入力デバイス種別.Keyboard )\r
35                                         {\r
36                                                 this._Keyboard = device;\r
37                                                 return device;\r
38                                         }\r
39                                 }\r
40                                 return null;\r
41                         }\r
42                 }\r
43                 public IInputDevice Mouse\r
44                 {\r
45                         get\r
46                         {\r
47                                 if( this._Mouse != null )\r
48                                 {\r
49                                         return this._Mouse;\r
50                                 }\r
51                                 foreach( IInputDevice device in this.list入力デバイス )\r
52                                 {\r
53                                         if( device.e入力デバイス種別 == E入力デバイス種別.Mouse )\r
54                                         {\r
55                                                 this._Mouse = device;\r
56                                                 return device;\r
57                                         }\r
58                                 }\r
59                                 return null;\r
60                         }\r
61                 }\r
62 \r
63 \r
64                 // コンストラクタ\r
65                 public CInput管理( IntPtr hWnd )\r
66                 {\r
67                         CInput管理初期化( hWnd, true );\r
68                 }\r
69                 public CInput管理( IntPtr hWnd, bool bUseMidiIn )\r
70                 {\r
71                         CInput管理初期化( hWnd, bUseMidiIn );\r
72                 }\r
73 \r
74                 public void CInput管理初期化( IntPtr hWnd, bool bUseMidiIn )\r
75                 {\r
76                         this.directInput = new DirectInput();\r
77                         // this.timer = new CTimer( CTimer.E種別.MultiMedia );\r
78 \r
79                         this.list入力デバイス = new List<IInputDevice>( 10 );\r
80                         #region [ Enumerate keyboard/mouse: exception is masked if keyboard/mouse is not connected ]\r
81                         CInputKeyboard cinputkeyboard = null;\r
82                         CInputMouse cinputmouse = null;\r
83                         try\r
84                         {\r
85                                 cinputkeyboard = new CInputKeyboard( hWnd, directInput );\r
86                                 cinputmouse = new CInputMouse( hWnd, directInput );\r
87                         }\r
88                         catch\r
89                         {\r
90                         }\r
91                         if (cinputkeyboard != null)\r
92                         {\r
93                                 this.list入力デバイス.Add( cinputkeyboard );\r
94                         }\r
95                         if ( cinputmouse != null )\r
96                         {\r
97                                 this.list入力デバイス.Add( cinputmouse );\r
98                         }\r
99                         #endregion\r
100                         #region [ Enumerate joypad ]\r
101                         foreach ( DeviceInstance instance in this.directInput.GetDevices( DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly ) )\r
102                         {\r
103                                 this.list入力デバイス.Add( new CInputJoystick( hWnd, instance, directInput ) );\r
104                         }\r
105                         #endregion\r
106                         if ( bUseMidiIn )\r
107                         {\r
108                                 this.proc = new CWin32.MidiInProc( this.MidiInCallback );\r
109                                 uint nMidiDevices = CWin32.midiInGetNumDevs();\r
110                                 Trace.TraceInformation( "MIDI入力デバイス数: {0}", nMidiDevices );\r
111                                 for ( uint i = 0; i < nMidiDevices; i++ )\r
112                                 {\r
113                                         CInputMIDI item = new CInputMIDI( i );\r
114                                         this.list入力デバイス.Add( item );\r
115                                         CWin32.MIDIINCAPS lpMidiInCaps = new CWin32.MIDIINCAPS();\r
116                                         uint num3 = CWin32.midiInGetDevCaps( i, ref lpMidiInCaps, (uint) Marshal.SizeOf( lpMidiInCaps ) );\r
117                                         if ( num3 != 0 )\r
118                                         {\r
119                                                 Trace.TraceError( "MIDI In: Device{0}: midiInDevCaps(): {1:X2}: ", i, num3 );\r
120                                         }\r
121                                         else if ( ( CWin32.midiInOpen( ref item.hMidiIn, i, this.proc, 0, 0x30000 ) == 0 ) && ( item.hMidiIn != 0 ) )\r
122                                         {\r
123                                                 CWin32.midiInStart( item.hMidiIn );\r
124                                                 Trace.TraceInformation( "MIDI In: [{0}] \"{1}\" の入力受付を開始しました。", i, lpMidiInCaps.szPname );\r
125                                         }\r
126                                         else\r
127                                         {\r
128                                                 Trace.TraceError( "MIDI In: [{0}] \"{1}\" の入力受付の開始に失敗しました。", i, lpMidiInCaps.szPname );\r
129                                         }\r
130                                 }\r
131                         }\r
132                         else\r
133                         {\r
134                                 Trace.TraceInformation( "DTXVモードのため、MIDI入力は使用しません。" );\r
135                         }\r
136                 }\r
137                 \r
138                 \r
139                 // メソッド\r
140 \r
141                 public IInputDevice Joystick( int ID )\r
142                 {\r
143                         foreach( IInputDevice device in this.list入力デバイス )\r
144                         {\r
145                                 if( ( device.e入力デバイス種別 == E入力デバイス種別.Joystick ) && ( device.ID == ID ) )\r
146                                 {\r
147                                         return device;\r
148                                 }\r
149                         }\r
150                         return null;\r
151                 }\r
152                 public IInputDevice Joystick( string GUID )\r
153                 {\r
154                         foreach( IInputDevice device in this.list入力デバイス )\r
155                         {\r
156                                 if( ( device.e入力デバイス種別 == E入力デバイス種別.Joystick ) && device.GUID.Equals( GUID ) )\r
157                                 {\r
158                                         return device;\r
159                                 }\r
160                         }\r
161                         return null;\r
162                 }\r
163                 public IInputDevice MidiIn( int ID )\r
164                 {\r
165                         foreach( IInputDevice device in this.list入力デバイス )\r
166                         {\r
167                                 if( ( device.e入力デバイス種別 == E入力デバイス種別.MidiIn ) && ( device.ID == ID ) )\r
168                                 {\r
169                                         return device;\r
170                                 }\r
171                         }\r
172                         return null;\r
173                 }\r
174                 public void tポーリング( bool bWindowがアクティブ中, bool bバッファ入力を使用する )\r
175                 {\r
176                         lock( this.objMidiIn排他用 )\r
177                         {\r
178 //                              foreach( IInputDevice device in this.list入力デバイス )\r
179                                 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().\r
180                                 {\r
181                                         IInputDevice device = this.list入力デバイス[i];\r
182                                         try\r
183                                         {\r
184                                                 device.tポーリング(bWindowがアクティブ中, bバッファ入力を使用する);\r
185                                         }\r
186                                         catch (SharpDX.SharpDXException e)                                                                              // #24016 2011.1.6 yyagi: catch exception for unplugging USB joystick, and remove the device object from the polling items.\r
187                                         {\r
188                                                 if( e.ResultCode == ResultCode.OtherApplicationHasPriority )\r
189                                                 {\r
190                                                         // #xxxxx: 2017.5.9: from: このエラーの時は、何もしない。\r
191                                                 }\r
192                                                 else\r
193                                                 {\r
194                                                         // #xxxxx: 2017.5.9: from: その他のエラーの場合は、デバイスが外されたと想定してRemoveする。\r
195                                                         this.list入力デバイス.Remove( device );\r
196                                                         device.Dispose();\r
197                                                         Trace.TraceError( "tポーリング時に対象deviceが抜かれており例外発生。同deviceをポーリング対象からRemoveしました。" );\r
198                                                 }\r
199                                         }\r
200                                 }\r
201                         }\r
202                 }\r
203 \r
204                 #region [ IDisposable+α ]\r
205                 //-----------------\r
206                 public void Dispose()\r
207                 {\r
208                         this.Dispose( true );\r
209                 }\r
210                 public void Dispose( bool disposeManagedObjects )\r
211                 {\r
212                         if( !this.bDisposed済み )\r
213                         {\r
214                                 if( disposeManagedObjects )\r
215                                 {\r
216                                         foreach( IInputDevice device in this.list入力デバイス )\r
217                                         {\r
218                                                 CInputMIDI tmidi = device as CInputMIDI;\r
219                                                 if( tmidi != null )\r
220                                                 {\r
221                                                         CWin32.midiInStop( tmidi.hMidiIn );\r
222                                                         CWin32.midiInReset( tmidi.hMidiIn );\r
223                                                         CWin32.midiInClose( tmidi.hMidiIn );\r
224                                                         Trace.TraceInformation( "MIDI In: [{0}] を停止しました。", new object[] { tmidi.ID } );\r
225                                                 }\r
226                                         }\r
227                                         foreach( IInputDevice device2 in this.list入力デバイス )\r
228                                         {\r
229                                                 device2.Dispose();\r
230                                         }\r
231                                         lock( this.objMidiIn排他用 )\r
232                                         {\r
233                                                 this.list入力デバイス.Clear();\r
234                                         }\r
235 \r
236                                         this.directInput.Dispose();\r
237 \r
238                                         //if( this.timer != null )\r
239                                         //{\r
240                                         //    this.timer.Dispose();\r
241                                         //    this.timer = null;\r
242                                         //}\r
243                                 }\r
244                                 this.bDisposed済み = true;\r
245                         }\r
246                 }\r
247                 ~CInput管理()\r
248                 {\r
249                         this.Dispose( false );\r
250                         GC.KeepAlive( this );\r
251                 }\r
252                 //-----------------\r
253                 #endregion\r
254 \r
255 \r
256                 // その他\r
257 \r
258                 #region [ private ]\r
259                 //-----------------\r
260                 private DirectInput directInput;\r
261                 private IInputDevice _Keyboard;\r
262                 private IInputDevice _Mouse;\r
263                 private bool bDisposed済み;\r
264                 private List<uint> listHMIDIIN = new List<uint>( 8 );\r
265                 private object objMidiIn排他用 = new object();\r
266                 private CWin32.MidiInProc proc;\r
267 //              private CTimer timer;\r
268 \r
269                 private void MidiInCallback( uint hMidiIn, uint wMsg, int dwInstance, int dwParam1, int dwParam2 )\r
270                 {\r
271                         int p = dwParam1 & 0xF0;\r
272                         if( wMsg != CWin32.MIM_DATA || ( p != 0x80 && p != 0x90 && p != 0xB0 ) )\r
273                                 return;\r
274 \r
275             long time = CSound管理.rc演奏用タイマ.nシステム時刻;  // lock前に取得。演奏用タイマと同じタイマを使うことで、BGMと譜面、入力ずれを防ぐ。\r
276 \r
277                         lock( this.objMidiIn排他用 )\r
278                         {\r
279                                 if( ( this.list入力デバイス != null ) && ( this.list入力デバイス.Count != 0 ) )\r
280                                 {\r
281                                         foreach( IInputDevice device in this.list入力デバイス )\r
282                                         {\r
283                                                 CInputMIDI tmidi = device as CInputMIDI;\r
284                                                 if( ( tmidi != null ) && ( tmidi.hMidiIn == hMidiIn ) )\r
285                                                 {\r
286                                                         tmidi.tメッセージからMIDI信号のみ受信( wMsg, dwInstance, dwParam1, dwParam2, time );\r
287                                                         break;\r
288                                                 }\r
289                                         }\r
290                                 }\r
291                         }\r
292                 }\r
293                 //-----------------\r
294                 #endregion\r
295         }\r
296 }\r