Media key support (#294)

* Introduce type for KeystrokeAction

* Increment dataModelVersion

New property 'type' for KeystrokeAction

* Mapping for media keys

* Media key selecting support for KeypressTab

* refactor: Use more meaningful name (selectedScancodeOption)

* Store the keystroke type in key action type instead of a new field
This commit is contained in:
József Farkas
2017-06-11 12:11:12 +02:00
committed by László Monda
parent 8e823b57b4
commit efe7e95b3e
13 changed files with 724 additions and 388 deletions

View File

@@ -2,7 +2,7 @@
<b class="setting-label">Scancode:</b>
<select2
[data]="scanCodeGroups"
[value]="scanCode.toString()"
[value]="selectedScancodeOption.id"
(valueChanged)="onScancodeChange($event)"
[width]="200"
[options]="options"
@@ -47,4 +47,4 @@
<i class="fa fa-info-circle"></i>
When a key is configured as layer switcher key, you can't assign other functions to it.
To assign a scancode to the key, set the <em>Layer action</em> to <em>None</em>.
</div>
</div>

View File

@@ -6,6 +6,7 @@ import { KeyAction, KeystrokeAction } from '../../../../config-serializer/config
import { Tab } from '../tab';
import { MapperService } from '../../../../services/mapper.service';
import { KeystrokeType } from '../../../../config-serializer/config-items/key-action/keystroke-type';
@Component({
selector: 'keypress-tab',
@@ -16,18 +17,18 @@ export class KeypressTabComponent extends Tab implements OnChanges {
@Input() defaultKeyAction: KeyAction;
@Input() longPressEnabled: boolean;
private leftModifiers: string[];
private rightModifiers: string[];
leftModifiers: string[];
rightModifiers: string[];
private leftModifierSelects: boolean[];
private rightModifierSelects: boolean[];
leftModifierSelects: boolean[];
rightModifierSelects: boolean[];
private scanCodeGroups: Array<Select2OptionData>;
private longPressGroups: Array<Select2OptionData>;
private options: Select2Options;
scanCodeGroups: Array<Select2OptionData>;
longPressGroups: Array<Select2OptionData>;
options: Select2Options;
private scanCode: number;
private selectedLongPressIndex: number;
selectedScancodeOption: Select2OptionData;
selectedLongPressIndex: number;
constructor(private mapper: MapperService) {
super();
@@ -41,7 +42,7 @@ export class KeypressTabComponent extends Tab implements OnChanges {
this.longPressGroups = require('json-loader!./longPress.json');
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
this.scanCode = 0;
this.selectedScancodeOption = this.scanCodeGroups[0];
this.selectedLongPressIndex = -1;
this.options = {
templateResult: this.scanCodeTemplateResult,
@@ -70,11 +71,11 @@ export class KeypressTabComponent extends Tab implements OnChanges {
return (keystrokeAction) ? (keystrokeAction.scancode > 0 || keystrokeAction.modifierMask > 0) : false;
}
onKeysCapture(event: {code: number, left: boolean[], right: boolean[]}) {
onKeysCapture(event: { code: number, left: boolean[], right: boolean[] }) {
if (event.code) {
this.scanCode = event.code;
this.selectedScancodeOption = this.findScancodeOptionByScancode(event.code, KeystrokeType.basic);
} else {
this.scanCode = 0;
this.selectedScancodeOption = this.scanCodeGroups[0];
}
this.leftModifierSelects = event.left;
@@ -87,8 +88,8 @@ export class KeypressTabComponent extends Tab implements OnChanges {
return false;
}
const keystrokeAction: KeystrokeAction = <KeystrokeAction>keyAction;
// Restore scancode
this.scanCode = keystrokeAction.scancode || 0;
// Restore selectedScancodeOption
this.selectedScancodeOption = this.findScancodeOptionByScancode(keystrokeAction.scancode || 0, keystrokeAction.type);
const leftModifiersLength: number = this.leftModifiers.length;
@@ -112,8 +113,13 @@ export class KeypressTabComponent extends Tab implements OnChanges {
toKeyAction(): KeystrokeAction {
const keystrokeAction: KeystrokeAction = new KeystrokeAction();
keystrokeAction.scancode = this.scanCode;
const scTypePair = this.toScancodeTypePair(this.selectedScancodeOption);
keystrokeAction.scancode = scTypePair[0];
if (scTypePair[1] === 'media') {
keystrokeAction.type = KeystrokeType.shortMedia;
} else {
keystrokeAction.type = KeystrokeType[scTypePair[1]];
}
keystrokeAction.modifierMask = 0;
const modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0);
for (let i = 0; i < modifiers.length; ++i) {
@@ -137,10 +143,10 @@ export class KeypressTabComponent extends Tab implements OnChanges {
if (state.additional && state.additional.explanation) {
return jQuery(
'<span class="select2-item">'
+ '<span>' + state.text + '</span>'
+ '<span class="scancode--searchterm"> '
+ state.additional.explanation
+ '</span>' +
+ '<span>' + state.text + '</span>'
+ '<span class="scancode--searchterm"> '
+ state.additional.explanation
+ '</span>' +
'</span>'
);
} else {
@@ -155,12 +161,65 @@ export class KeypressTabComponent extends Tab implements OnChanges {
this.validAction.emit(this.keyActionValid());
}
onLongpressChange(event: {value: string}) {
onLongpressChange(event: { value: string }) {
this.selectedLongPressIndex = +event.value;
}
onScancodeChange(event: {value: string}) {
this.scanCode = +event.value;
onScancodeChange(event: { value: string }) {
const id: string = event.value;
// ng2-select2 should provide the selectedOption in an upcoming release
// TODO: change this when it has become available
this.selectedScancodeOption = this.findScancodeOptionById(id);
this.validAction.emit(this.keyActionValid());
}
private findScancodeOptionBy(predicate: (option: Select2OptionData) => boolean): Select2OptionData {
let selectedOption: Select2OptionData;
const scanCodeGroups: Select2OptionData[] = [...this.scanCodeGroups];
while (scanCodeGroups.length > 0) {
const scanCodeGroup = scanCodeGroups.shift();
if (predicate(scanCodeGroup)) {
selectedOption = scanCodeGroup;
break;
}
scanCodeGroups.push(...scanCodeGroup.children);
}
return selectedOption;
}
private findScancodeOptionById(id: string): Select2OptionData {
return this.findScancodeOptionBy(option => option.id === id);
}
private findScancodeOptionByScancode(scancode: number, type: KeystrokeType): Select2OptionData {
const typeToFind: string = type === KeystrokeType.shortMedia || KeystrokeType.longMedia ? 'media' : KeystrokeType[type];
return this.findScancodeOptionBy((option: Select2OptionData) => {
const additional = option.additional;
if (additional && additional.scancode === scancode && additional.type === typeToFind) {
return true;
} else if (+option.id === scancode) {
return true;
} else {
return false;
}
});
}
private toScancodeTypePair(option: Select2OptionData): [number, string] {
let scanCode: number;
let type: string;
if (option.additional) {
scanCode = option.additional.scancode ? option.additional.scancode : 0;
type = option.additional.type || 'basic';
} else {
scanCode = +option.id;
type = 'basic';
}
return [scanCode, type];
}
}

View File

@@ -559,7 +559,11 @@
"children": [
{
"id": "127",
"text": "Mute"
"text": "Mute",
"additional": {
"type": "media",
"scancode": 226
}
},
{
"id": "128",
@@ -591,4 +595,4 @@
}
]
}
]
]

View File

@@ -220,7 +220,7 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy {
if (!keyAction.hasActiveModifier() && keyAction.hasScancode()) {
const scancode: number = keyAction.scancode;
newLabelSource = this.mapper.scanCodeToText(scancode);
newLabelSource = this.mapper.scanCodeToText(scancode, keyAction.type);
if (this.mapper.hasScancodeIcon(scancode)) {
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode);
this.labelType = LabelTypes.SingleIcon;

View File

@@ -131,7 +131,7 @@ export class SvgKeystrokeKeyComponent implements OnInit, OnChanges {
let newLabelSource: string[];
if (this.keystrokeAction.hasScancode()) {
const scancode: number = this.keystrokeAction.scancode;
newLabelSource = this.mapper.scanCodeToText(scancode);
newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type);
if (newLabelSource) {
if (newLabelSource.length === 1) {
this.labelSource = newLabelSource[0];

View File

@@ -245,7 +245,8 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
if (keystrokeAction.hasScancode()) {
let value: string = keystrokeAction.scancode.toString();
const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode) || []).join(', ');
const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode, keystrokeAction.type) || [])
.join(', ');
if (scanCodeTexts.length > 0) {
value += ' (' + scanCodeTexts + ')';
}

View File

@@ -7,17 +7,18 @@ export enum KeyActionId {
NoneAction = 0,
KeystrokeAction = 1,
/*
1 - 7 are reserved for KeystrokeAction
3 bits:
1 - 31 are reserved for KeystrokeAction
5 bits:
1: Do we have scancode?
2: Do we have modifiers?
3: Do we have longpress?
4-5: What kind of keystroke? (basic, short/long media, system)
*/
LastKeystrokeAction = 7, // TODO: remove this after refactoring the keyActionId check
SwitchLayerAction = 8,
SwitchKeymapAction = 9,
MouseAction = 10,
PlayMacroAction = 11
LastKeystrokeAction = 31, // TODO: remove this after refactoring the keyActionId check
SwitchLayerAction = 32,
SwitchKeymapAction = 33,
MouseAction = 34,
PlayMacroAction = 35
}
export let keyActionType = {

View File

@@ -3,6 +3,7 @@ import { UhkBuffer } from '../../UhkBuffer';
import { KeyModifiers } from '../KeyModifiers';
import { LongPressAction } from '../LongPressAction';
import { KeyAction, KeyActionId, keyActionType } from './KeyAction';
import { KeystrokeType } from './keystroke-type';
export enum KeystrokeActionFlag {
scancode = 1 << 0,
@@ -10,19 +11,31 @@ export enum KeystrokeActionFlag {
longPressAction = 1 << 2
}
const KEYSTROKE_ACTION_FLAG_LENGTH = 3;
interface JsonObjectKeystrokeAction {
keyActionType: string;
scancode?: number;
modifierMask?: number;
longPressAction?: string;
type?: string;
}
const MODIFIERS = ['LCtrl', 'LShift', 'LAlt', 'LSuper', 'RCtrl', 'RShift', 'RAlt', 'RSuper'];
const MODIFIERS = ['LCtrl', 'LShift', 'LAlt', 'LSuper', 'RCtrl', 'RShift', 'RAlt', 'RSuper'];
export class KeystrokeAction extends KeyAction {
@assertUInt8
scancode: number;
set scancode(scancode: number) {
this._scancode = scancode;
if (this.type !== KeystrokeType.shortMedia && this.type !== KeystrokeType.longMedia) {
return;
}
this.type = scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia;
}
get scancode() {
return this._scancode;
}
@assertUInt8
modifierMask: number;
@@ -30,19 +43,41 @@ export class KeystrokeAction extends KeyAction {
@assertEnum(LongPressAction)
longPressAction: LongPressAction;
set type(type: KeystrokeType) {
if (type === KeystrokeType.shortMedia || type === KeystrokeType.longMedia) {
type = this.scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia;
}
this._type = type;
}
get type() {
return this._type;
}
private _scancode: number;
@assertEnum(KeystrokeType)
private _type: KeystrokeType;
constructor(other?: KeystrokeAction) {
super();
if (!other) {
return;
}
this.scancode = other.scancode;
this.type = other.type;
this._scancode = other._scancode;
this.modifierMask = other.modifierMask;
this.longPressAction = other.longPressAction;
}
fromJsonObject(jsonObject: JsonObjectKeystrokeAction): KeystrokeAction {
this.assertKeyActionType(jsonObject);
this.scancode = jsonObject.scancode;
if (jsonObject.type === 'media') {
this.type = jsonObject.scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia;
} else {
this.type = KeystrokeType[jsonObject.type];
}
this._scancode = jsonObject.scancode;
this.modifierMask = jsonObject.modifierMask;
this.longPressAction = LongPressAction[jsonObject.longPressAction];
return this;
@@ -51,8 +86,9 @@ export class KeystrokeAction extends KeyAction {
fromBinary(buffer: UhkBuffer): KeystrokeAction {
const keyActionId: KeyActionId = this.readAndAssertKeyActionId(buffer);
const flags: number = keyActionId - KeyActionId.KeystrokeAction;
this.type = (flags >> 3) & 0b11;
if (flags & KeystrokeActionFlag.scancode) {
this.scancode = buffer.readUInt8();
this._scancode = this.type === KeystrokeType.longMedia ? buffer.readUInt16() : buffer.readUInt8();
}
if (flags & KeystrokeActionFlag.modifierMask) {
this.modifierMask = buffer.readUInt8();
@@ -68,8 +104,14 @@ export class KeystrokeAction extends KeyAction {
keyActionType: keyActionType.KeystrokeAction
};
if (this.type === KeystrokeType.shortMedia || this.type === KeystrokeType.longMedia) {
jsonObject.type = 'media';
} else {
jsonObject.type = KeystrokeType[this.type];
}
if (this.hasScancode()) {
jsonObject.scancode = this.scancode;
jsonObject.scancode = this._scancode;
}
if (this.hasActiveModifier()) {
@@ -85,33 +127,45 @@ export class KeystrokeAction extends KeyAction {
toBinary(buffer: UhkBuffer) {
let flags = 0;
const bufferData: number[] = [];
const toWrite: {
data: number,
long: boolean
}[] = [];
if (this.hasScancode()) {
flags |= KeystrokeActionFlag.scancode;
bufferData.push(this.scancode);
toWrite.push({ data: this._scancode, long: this.type === KeystrokeType.longMedia });
}
if (this.hasActiveModifier()) {
flags |= KeystrokeActionFlag.modifierMask;
bufferData.push(this.modifierMask);
toWrite.push({ data: this.modifierMask, long: false });
}
if (this.hasLongPressAction()) {
flags |= KeystrokeActionFlag.longPressAction;
bufferData.push(this.longPressAction);
toWrite.push({ data: this.longPressAction, long: false });
}
buffer.writeUInt8(KeyActionId.KeystrokeAction + flags);
for (let i = 0; i < bufferData.length; ++i) {
buffer.writeUInt8(bufferData[i]);
const TYPE_OFFSET = flags + (this.type << KEYSTROKE_ACTION_FLAG_LENGTH);
buffer.writeUInt8(KeyActionId.KeystrokeAction + TYPE_OFFSET);
for (let i = 0; i < toWrite.length; ++i) {
if (toWrite[i].long) {
buffer.writeUInt16(toWrite[i].data);
} else {
buffer.writeUInt8(toWrite[i].data);
}
}
}
toString(): string {
const properties: string[] = [];
properties.push(`type="${KeystrokeType[this.type]}"`);
if (this.hasScancode()) {
properties.push(`scancode="${this.scancode}"`);
properties.push(`scancode="${this._scancode}"`);
}
if (this.hasActiveModifier()) {
properties.push(`modifierMask="${this.modifierMask}"`);
@@ -136,7 +190,7 @@ export class KeystrokeAction extends KeyAction {
}
hasScancode(): boolean {
return !!this.scancode;
return !!this._scancode;
}
hasOnlyOneActiveModifier(): boolean {

View File

@@ -0,0 +1,6 @@
export enum KeystrokeType {
basic,
shortMedia,
longMedia,
system
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,13 @@ const __svg__ = { path: '../../../images/icons/**/*.svg', name: 'assets/compiled
/* tslint:enable:variable-name */
import { Injectable } from '@angular/core';
import { KeystrokeType } from '../config-serializer/config-items/key-action/keystroke-type';
@Injectable()
export class MapperService {
private scanCodeTextMap: Map<number, string[]>;
private basicScanCodeTextMap: Map<number, string[]>;
private mediaScanCodeTextMap: Map<number, string[]>;
private scanCodeFileName: Map<number, string>;
private nameToFileName: Map<string, string>;
@@ -18,8 +20,18 @@ export class MapperService {
this.initNameToFileNames();
}
public scanCodeToText(scanCode: number): string[] {
return this.scanCodeTextMap.get(scanCode);
public scanCodeToText(scanCode: number, type: KeystrokeType = KeystrokeType.basic): string[] {
let map: Map<number, string[]>;
switch (type) {
case KeystrokeType.shortMedia:
case KeystrokeType.longMedia:
map = this.mediaScanCodeTextMap;
break;
default:
map = this.basicScanCodeTextMap;
break;
}
return map.get(scanCode);
}
public hasScancodeIcon(scancode: number): boolean {
@@ -48,130 +60,132 @@ export class MapperService {
// TODO: read the mapping from JSON
private initScanCodeTextMap(): void {
this.scanCodeTextMap = new Map<number, string[]>();
this.scanCodeTextMap.set(4, ['A']);
this.scanCodeTextMap.set(5, ['B']);
this.scanCodeTextMap.set(6, ['C']);
this.scanCodeTextMap.set(7, ['D']);
this.scanCodeTextMap.set(8, ['E']);
this.scanCodeTextMap.set(9, ['F']);
this.scanCodeTextMap.set(10, ['G']);
this.scanCodeTextMap.set(11, ['H']);
this.scanCodeTextMap.set(12, ['I']);
this.scanCodeTextMap.set(13, ['J']);
this.scanCodeTextMap.set(14, ['K']);
this.scanCodeTextMap.set(15, ['L']);
this.scanCodeTextMap.set(16, ['M']);
this.scanCodeTextMap.set(17, ['N']);
this.scanCodeTextMap.set(18, ['O']);
this.scanCodeTextMap.set(19, ['P']);
this.scanCodeTextMap.set(20, ['Q']);
this.scanCodeTextMap.set(21, ['R']);
this.scanCodeTextMap.set(22, ['S']);
this.scanCodeTextMap.set(23, ['T']);
this.scanCodeTextMap.set(24, ['U']);
this.scanCodeTextMap.set(25, ['V']);
this.scanCodeTextMap.set(26, ['W']);
this.scanCodeTextMap.set(27, ['X']);
this.scanCodeTextMap.set(28, ['Y']);
this.scanCodeTextMap.set(29, ['Z']);
this.scanCodeTextMap.set(30, ['1', '!']);
this.scanCodeTextMap.set(31, ['2', '@']);
this.scanCodeTextMap.set(32, ['3', '#']);
this.scanCodeTextMap.set(33, ['4', '$']);
this.scanCodeTextMap.set(34, ['5', '%']);
this.scanCodeTextMap.set(35, ['6', '^']);
this.scanCodeTextMap.set(36, ['7', '&']);
this.scanCodeTextMap.set(37, ['8', '*']);
this.scanCodeTextMap.set(38, ['9', '(']);
this.scanCodeTextMap.set(39, ['0', ')']);
this.scanCodeTextMap.set(40, ['Enter']);
this.scanCodeTextMap.set(41, ['Esc']);
this.scanCodeTextMap.set(42, ['Backspace']);
this.scanCodeTextMap.set(43, ['Tab']);
this.scanCodeTextMap.set(44, ['Space']);
this.scanCodeTextMap.set(45, ['-', '_']);
this.scanCodeTextMap.set(46, ['=', '+']);
this.scanCodeTextMap.set(47, ['[', '{']);
this.scanCodeTextMap.set(48, [']', '}']);
this.scanCodeTextMap.set(49, ['\\', '|']);
this.scanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']);
this.scanCodeTextMap.set(51, [';', ':']);
this.scanCodeTextMap.set(52, ['\'', '"']);
this.scanCodeTextMap.set(53, ['`', '~']);
this.scanCodeTextMap.set(54, [',', '<']);
this.scanCodeTextMap.set(55, ['.', '>']);
this.scanCodeTextMap.set(56, ['/', '?']);
this.scanCodeTextMap.set(57, ['Caps Lock']);
this.scanCodeTextMap.set(58, ['F1']);
this.scanCodeTextMap.set(59, ['F2']);
this.scanCodeTextMap.set(60, ['F3']);
this.scanCodeTextMap.set(61, ['F4']);
this.scanCodeTextMap.set(62, ['F5']);
this.scanCodeTextMap.set(63, ['F6']);
this.scanCodeTextMap.set(64, ['F7']);
this.scanCodeTextMap.set(65, ['F8']);
this.scanCodeTextMap.set(66, ['F9']);
this.scanCodeTextMap.set(67, ['F10']);
this.scanCodeTextMap.set(68, ['F11']);
this.scanCodeTextMap.set(69, ['F12']);
this.scanCodeTextMap.set(70, ['PrtScn']);
this.scanCodeTextMap.set(71, ['Scroll Lock']);
this.scanCodeTextMap.set(72, ['Pause']);
this.scanCodeTextMap.set(73, ['Insert']);
this.scanCodeTextMap.set(74, ['Home']);
this.scanCodeTextMap.set(75, ['PgUp']);
this.scanCodeTextMap.set(76, ['Del']);
this.scanCodeTextMap.set(77, ['End']);
this.scanCodeTextMap.set(78, ['PgDn']);
this.scanCodeTextMap.set(79, ['Right Arrow']);
this.scanCodeTextMap.set(80, ['Left Arrow']);
this.scanCodeTextMap.set(81, ['Down Arrow']);
this.scanCodeTextMap.set(82, ['Up Arrow']);
this.scanCodeTextMap.set(83, ['Num Lock']);
this.scanCodeTextMap.set(84, ['/']);
this.scanCodeTextMap.set(85, ['*']);
this.scanCodeTextMap.set(86, ['-']);
this.scanCodeTextMap.set(87, ['+']);
this.scanCodeTextMap.set(88, ['Enter']);
this.scanCodeTextMap.set(89, ['end', '1']);
this.scanCodeTextMap.set(90, ['2']);
this.scanCodeTextMap.set(91, ['pgdn', '3']);
this.scanCodeTextMap.set(92, ['4']);
this.scanCodeTextMap.set(93, ['5']);
this.scanCodeTextMap.set(94, ['6']);
this.scanCodeTextMap.set(95, ['home', '7']);
this.scanCodeTextMap.set(96, ['8']);
this.scanCodeTextMap.set(97, ['pgup', '9']);
this.scanCodeTextMap.set(98, ['Insert', '0']);
this.scanCodeTextMap.set(99, ['Del', '.']);
this.scanCodeTextMap.set(104, ['F13']);
this.scanCodeTextMap.set(105, ['F14']);
this.scanCodeTextMap.set(106, ['F15']);
this.scanCodeTextMap.set(107, ['F16']);
this.scanCodeTextMap.set(108, ['F17']);
this.scanCodeTextMap.set(109, ['F18']);
this.scanCodeTextMap.set(110, ['F19']);
this.scanCodeTextMap.set(111, ['F20']);
this.scanCodeTextMap.set(112, ['F21']);
this.scanCodeTextMap.set(113, ['F22']);
this.scanCodeTextMap.set(114, ['F23']);
this.scanCodeTextMap.set(115, ['F24']);
this.scanCodeTextMap.set(118, ['Menu']);
this.scanCodeTextMap.set(176, ['00']);
this.scanCodeTextMap.set(177, ['000']);
this.scanCodeTextMap.set(232, ['Play']);
this.scanCodeTextMap.set(233, ['Stop']);
this.scanCodeTextMap.set(234, ['Prev']);
this.scanCodeTextMap.set(235, ['Next']);
this.scanCodeTextMap.set(236, ['Eject']);
this.scanCodeTextMap.set(237, ['Vol +']);
this.scanCodeTextMap.set(238, ['Vol -']);
this.scanCodeTextMap.set(239, ['Mute']);
this.scanCodeTextMap.set(240, ['WWW']);
this.scanCodeTextMap.set(241, ['Bckwrd']);
this.scanCodeTextMap.set(242, ['Frwrd']);
this.scanCodeTextMap.set(243, ['Cancel']);
this.basicScanCodeTextMap = new Map<number, string[]>();
this.basicScanCodeTextMap.set(4, ['A']);
this.basicScanCodeTextMap.set(5, ['B']);
this.basicScanCodeTextMap.set(6, ['C']);
this.basicScanCodeTextMap.set(7, ['D']);
this.basicScanCodeTextMap.set(8, ['E']);
this.basicScanCodeTextMap.set(9, ['F']);
this.basicScanCodeTextMap.set(10, ['G']);
this.basicScanCodeTextMap.set(11, ['H']);
this.basicScanCodeTextMap.set(12, ['I']);
this.basicScanCodeTextMap.set(13, ['J']);
this.basicScanCodeTextMap.set(14, ['K']);
this.basicScanCodeTextMap.set(15, ['L']);
this.basicScanCodeTextMap.set(16, ['M']);
this.basicScanCodeTextMap.set(17, ['N']);
this.basicScanCodeTextMap.set(18, ['O']);
this.basicScanCodeTextMap.set(19, ['P']);
this.basicScanCodeTextMap.set(20, ['Q']);
this.basicScanCodeTextMap.set(21, ['R']);
this.basicScanCodeTextMap.set(22, ['S']);
this.basicScanCodeTextMap.set(23, ['T']);
this.basicScanCodeTextMap.set(24, ['U']);
this.basicScanCodeTextMap.set(25, ['V']);
this.basicScanCodeTextMap.set(26, ['W']);
this.basicScanCodeTextMap.set(27, ['X']);
this.basicScanCodeTextMap.set(28, ['Y']);
this.basicScanCodeTextMap.set(29, ['Z']);
this.basicScanCodeTextMap.set(30, ['1', '!']);
this.basicScanCodeTextMap.set(31, ['2', '@']);
this.basicScanCodeTextMap.set(32, ['3', '#']);
this.basicScanCodeTextMap.set(33, ['4', '$']);
this.basicScanCodeTextMap.set(34, ['5', '%']);
this.basicScanCodeTextMap.set(35, ['6', '^']);
this.basicScanCodeTextMap.set(36, ['7', '&']);
this.basicScanCodeTextMap.set(37, ['8', '*']);
this.basicScanCodeTextMap.set(38, ['9', '(']);
this.basicScanCodeTextMap.set(39, ['0', ')']);
this.basicScanCodeTextMap.set(40, ['Enter']);
this.basicScanCodeTextMap.set(41, ['Esc']);
this.basicScanCodeTextMap.set(42, ['Backspace']);
this.basicScanCodeTextMap.set(43, ['Tab']);
this.basicScanCodeTextMap.set(44, ['Space']);
this.basicScanCodeTextMap.set(45, ['-', '_']);
this.basicScanCodeTextMap.set(46, ['=', '+']);
this.basicScanCodeTextMap.set(47, ['[', '{']);
this.basicScanCodeTextMap.set(48, [']', '}']);
this.basicScanCodeTextMap.set(49, ['\\', '|']);
this.basicScanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']);
this.basicScanCodeTextMap.set(51, [';', ':']);
this.basicScanCodeTextMap.set(52, ['\'', '"']);
this.basicScanCodeTextMap.set(53, ['`', '~']);
this.basicScanCodeTextMap.set(54, [',', '<']);
this.basicScanCodeTextMap.set(55, ['.', '>']);
this.basicScanCodeTextMap.set(56, ['/', '?']);
this.basicScanCodeTextMap.set(57, ['Caps Lock']);
this.basicScanCodeTextMap.set(58, ['F1']);
this.basicScanCodeTextMap.set(59, ['F2']);
this.basicScanCodeTextMap.set(60, ['F3']);
this.basicScanCodeTextMap.set(61, ['F4']);
this.basicScanCodeTextMap.set(62, ['F5']);
this.basicScanCodeTextMap.set(63, ['F6']);
this.basicScanCodeTextMap.set(64, ['F7']);
this.basicScanCodeTextMap.set(65, ['F8']);
this.basicScanCodeTextMap.set(66, ['F9']);
this.basicScanCodeTextMap.set(67, ['F10']);
this.basicScanCodeTextMap.set(68, ['F11']);
this.basicScanCodeTextMap.set(69, ['F12']);
this.basicScanCodeTextMap.set(70, ['PrtScn']);
this.basicScanCodeTextMap.set(71, ['Scroll Lock']);
this.basicScanCodeTextMap.set(72, ['Pause']);
this.basicScanCodeTextMap.set(73, ['Insert']);
this.basicScanCodeTextMap.set(74, ['Home']);
this.basicScanCodeTextMap.set(75, ['PgUp']);
this.basicScanCodeTextMap.set(76, ['Del']);
this.basicScanCodeTextMap.set(77, ['End']);
this.basicScanCodeTextMap.set(78, ['PgDn']);
this.basicScanCodeTextMap.set(79, ['Right Arrow']);
this.basicScanCodeTextMap.set(80, ['Left Arrow']);
this.basicScanCodeTextMap.set(81, ['Down Arrow']);
this.basicScanCodeTextMap.set(82, ['Up Arrow']);
this.basicScanCodeTextMap.set(83, ['Num Lock']);
this.basicScanCodeTextMap.set(84, ['/']);
this.basicScanCodeTextMap.set(85, ['*']);
this.basicScanCodeTextMap.set(86, ['-']);
this.basicScanCodeTextMap.set(87, ['+']);
this.basicScanCodeTextMap.set(88, ['Enter']);
this.basicScanCodeTextMap.set(89, ['end', '1']);
this.basicScanCodeTextMap.set(90, ['2']);
this.basicScanCodeTextMap.set(91, ['pgdn', '3']);
this.basicScanCodeTextMap.set(92, ['4']);
this.basicScanCodeTextMap.set(93, ['5']);
this.basicScanCodeTextMap.set(94, ['6']);
this.basicScanCodeTextMap.set(95, ['home', '7']);
this.basicScanCodeTextMap.set(96, ['8']);
this.basicScanCodeTextMap.set(97, ['pgup', '9']);
this.basicScanCodeTextMap.set(98, ['Insert', '0']);
this.basicScanCodeTextMap.set(99, ['Del', '.']);
this.basicScanCodeTextMap.set(104, ['F13']);
this.basicScanCodeTextMap.set(105, ['F14']);
this.basicScanCodeTextMap.set(106, ['F15']);
this.basicScanCodeTextMap.set(107, ['F16']);
this.basicScanCodeTextMap.set(108, ['F17']);
this.basicScanCodeTextMap.set(109, ['F18']);
this.basicScanCodeTextMap.set(110, ['F19']);
this.basicScanCodeTextMap.set(111, ['F20']);
this.basicScanCodeTextMap.set(112, ['F21']);
this.basicScanCodeTextMap.set(113, ['F22']);
this.basicScanCodeTextMap.set(114, ['F23']);
this.basicScanCodeTextMap.set(115, ['F24']);
this.basicScanCodeTextMap.set(118, ['Menu']);
this.basicScanCodeTextMap.set(176, ['00']);
this.basicScanCodeTextMap.set(177, ['000']);
this.mediaScanCodeTextMap = new Map<number, string[]>();
this.mediaScanCodeTextMap.set(226, ['Mute']);
this.mediaScanCodeTextMap.set(232, ['Play']);
this.mediaScanCodeTextMap.set(233, ['Stop']);
this.mediaScanCodeTextMap.set(234, ['Prev']);
this.mediaScanCodeTextMap.set(235, ['Next']);
this.mediaScanCodeTextMap.set(236, ['Eject']);
this.mediaScanCodeTextMap.set(237, ['Vol +']);
this.mediaScanCodeTextMap.set(238, ['Vol -']);
this.mediaScanCodeTextMap.set(240, ['WWW']);
this.mediaScanCodeTextMap.set(241, ['Bckwrd']);
this.mediaScanCodeTextMap.set(242, ['Frwrd']);
this.mediaScanCodeTextMap.set(243, ['Cancel']);
}
private initScanCodeFileName(): void {