-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimulatorAPI.cs
More file actions
193 lines (165 loc) · 8.03 KB
/
SimulatorAPI.cs
File metadata and controls
193 lines (165 loc) · 8.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
////////////////////////////////////////////////////////////////////////////////////////////////////
// file: SimulatorAPI.cs
//
// summary: Implements the Simulator API class
////////////////////////////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
namespace Muster
{
/// <summary> A simulator API. </summary>
internal abstract class SimulatorAPI
{
/// <summary> Simulator name. </summary>
public string Name = "";
/// <summary> Number of bells. </summary>
public const int numberOfBells = 16;
/// <summary> Handle of the simulator process. </summary>
protected IntPtr SimulatorHandle = IntPtr.Zero;
/// <summary> Map from ringing events to characters. </summary>
protected Dictionary<string, char> RingingCommandToChar = new Dictionary<string, char>();
/// <summary> Map from keypress to ringing command where required. </summary>
protected Dictionary<string, string> KeypressToRingingCommand = new Dictionary<string, string>();
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Query if simulator process is connected. </summary>
///
/// <returns> True if simulator is connected, false if not. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public bool IsConnected()
{
return SimulatorHandle != IntPtr.Zero;
}
/// <summary> Searches for the simulator process. </summary>
public abstract bool FindInstance();
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Posts a message. </summary>
///
/// <param name="hWnd"> The window. </param>
/// <param name="Msg"> The message. </param>
/// <param name="wParam"> The parameter. </param>
/// <param name="lParam"> The parameter. </param>
///
/// <returns> True if it succeeds, false if it fails. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
[DllImport("user32.dll")]
protected static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
/// <summary> The Windows message keydown. </summary>
protected const int WM_KEYDOWN = 0x100;
/// <summary> The Windows message keyup. </summary>
protected const int WM_KEYUP = 0x101;
/// <summary> The Windows message character. </summary>
protected const int WM_CHAR = 0x102;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Sends a keystroke. </summary>
///
/// <param name="keyStroke"> The key stroke. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
protected abstract void SendKeystroke(char keyStroke);
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Sends a ringing event. </summary>
///
/// <param name="evt"> The event. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void SendRingingEvent(RingingEvent evt)
{
if (IsValidCommand(evt))
{
SendKeystroke(evt.ToChar());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Query if 'ringingEvent' is a valid simulator command. </summary>
///
/// <param name="ringingEvent"> The ringing event. </param>
///
/// <returns> True if a valid simulator command, false if not. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public bool IsValidCommand(RingingEvent ringingEvent)
{
return RingingCommandToChar.ContainsKey(ringingEvent.ToString());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Ring bell. </summary>
///
/// <param name="keyStroke"> The key stroke. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void RingBell(char keyStroke)
{
if (IsValidKeystroke(keyStroke))
{
SendKeystroke(keyStroke);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Query if 'key' is a valid simulator keystroke. </summary>
///
/// <param name="key"> The key. </param>
///
/// <returns> True if a valid simulator keystroke, false if not. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public bool IsValidKeystroke(char key)
{
return RingingCommandToChar.ContainsValue(key);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Map a command to a ringing event. </summary>
///
/// <param name="command"> The command. </param>
///
/// <returns> The ringing event for the command. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public RingingEvent FindEventForCommand(string command)
{
if (RingingCommandToChar.ContainsKey(command))
{
return new RingingEvent(command, RingingCommandToChar[command]);
}
else
return null;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Map a character to a ringing event. </summary>
///
/// <param name="keyChar"> The character. </param>
///
/// <returns> The ringing event for the character. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public RingingEvent FindEventForChar(char keyChar)
{
var reversed = RingingCommandToChar.ToDictionary(x => x.Value, x => x.Key);
if (reversed.ContainsKey(keyChar))
{
return new RingingEvent(reversed[keyChar], keyChar);
}
else
return null;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Map a keypress to a ringing event. </summary>
///
/// <param name="keyStroke"> The keypress. </param>
///
/// <returns> The ringing event for the keypress. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public RingingEvent FindEventForKey(string keyCode)
{
if (KeypressToRingingCommand.ContainsKey(keyCode))
{
// The char sent over the network does not match the key directly
// Apply mapping
var command = KeypressToRingingCommand[keyCode];
return FindEventForCommand(command);
}
else if (keyCode.Length == 1)
{
// The char sent over the network matches the key press.
return FindEventForChar(keyCode[0]);
}
else
return null;
}
}
}