Better implementation of PPT and key listener.
parent
69b4730bd8
commit
f37b918a5b
|
@ -5,22 +5,59 @@ namespace ppt {
|
||||||
KEY_TYPED
|
KEY_TYPED
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KeyEvent {
|
export enum SpecialKey {
|
||||||
|
CTRL,
|
||||||
|
WINDOWS,
|
||||||
|
SHIFT,
|
||||||
|
ALT
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KeyDescriptor {
|
||||||
|
key_code: string;
|
||||||
|
|
||||||
|
key_ctrl: boolean;
|
||||||
|
key_windows: boolean;
|
||||||
|
key_shift: boolean;
|
||||||
|
key_alt: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KeyEvent extends KeyDescriptor {
|
||||||
readonly type: EventType;
|
readonly type: EventType;
|
||||||
|
|
||||||
readonly key: string;
|
readonly key: string;
|
||||||
readonly key_code: string;
|
}
|
||||||
|
|
||||||
readonly key_ctrl: boolean;
|
export interface KeyHook extends KeyDescriptor {
|
||||||
readonly key_windows: boolean;
|
cancel: boolean;
|
||||||
readonly key_shift: boolean;
|
|
||||||
readonly key_alt: boolean;
|
|
||||||
|
callback_press: () => any;
|
||||||
|
callback_release: () => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function key_description(key: KeyDescriptor) {
|
||||||
|
let result = "";
|
||||||
|
if(key.key_shift)
|
||||||
|
result += " + Shift";
|
||||||
|
if(key.key_alt)
|
||||||
|
result += " + Alt";
|
||||||
|
if(key.key_ctrl)
|
||||||
|
result += " + CTRL";
|
||||||
|
if(key.key_windows)
|
||||||
|
result += " + Win";
|
||||||
|
|
||||||
|
result += " + " + (key.key_code ? key.key_code : "unset");
|
||||||
|
return result.substr(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare function initialize() : Promise<void>;
|
export declare function initialize() : Promise<void>;
|
||||||
export declare function finalize(); /* most the times not really required */
|
export declare function finalize(); /* most the times not really required */
|
||||||
|
|
||||||
export declare function register_key_hook(callback: (event: KeyEvent) => any, cancel: boolean);
|
export declare function register_key_listener(listener: (_: KeyEvent) => any);
|
||||||
export declare function unregister_key_hook(callback: (event: KeyEvent) => any);
|
export declare function unregister_key_listener(listener: (_: KeyEvent) => any);
|
||||||
|
|
||||||
|
export declare function register_key_hook(hook: KeyHook);
|
||||||
|
export declare function unregister_key_hook(hook: KeyHook);
|
||||||
|
|
||||||
|
export declare function key_pressed(code: string | SpecialKey) : boolean;
|
||||||
}
|
}
|
|
@ -122,6 +122,7 @@ function loadDebug() {
|
||||||
console.log("Adding browser audio player");
|
console.log("Adding browser audio player");
|
||||||
custom_scripts.push(["js/audio/AudioPlayer.js"]);
|
custom_scripts.push(["js/audio/AudioPlayer.js"]);
|
||||||
custom_scripts.push(["js/audio/WebCodec.js"]);
|
custom_scripts.push(["js/audio/WebCodec.js"]);
|
||||||
|
custom_scripts.push(["js/WebPPTListener.js"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
load_wait_scripts([
|
load_wait_scripts([
|
||||||
|
@ -186,6 +187,7 @@ function loadDebug() {
|
||||||
"js/chat.js",
|
"js/chat.js",
|
||||||
"js/Identity.js",
|
"js/Identity.js",
|
||||||
|
|
||||||
|
"js/PPTListener.js",
|
||||||
...custom_scripts
|
...custom_scripts
|
||||||
]).then(() => load_wait_scripts([
|
]).then(() => load_wait_scripts([
|
||||||
"js/codec/CodecWrapperWorker.js"
|
"js/codec/CodecWrapperWorker.js"
|
||||||
|
|
|
@ -135,6 +135,11 @@ function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ppt.initialize().catch(error => {
|
||||||
|
console.error("Failed to initialize ppt!");
|
||||||
|
//TODO error notification?
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let tag = $("#tmpl_music_frame").renderTag({
|
let tag = $("#tmpl_music_frame").renderTag({
|
||||||
//thumbnail: "img/loading_image.svg"
|
//thumbnail: "img/loading_image.svg"
|
||||||
|
|
|
@ -29,7 +29,7 @@ class StaticSettings {
|
||||||
if (typeof input === "string") return input as string;
|
if (typeof input === "string") return input as string;
|
||||||
else if (typeof input === "number") return input.toString();
|
else if (typeof input === "number") return input.toString();
|
||||||
else if (typeof input === "boolean") return input ? "1" : "0";
|
else if (typeof input === "boolean") return input ? "1" : "0";
|
||||||
else if (typeof input == "undefined") return undefined;
|
else if (typeof input === "undefined") return undefined;
|
||||||
return JSON.stringify(input);
|
return JSON.stringify(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
/// <reference path="../../voice/AudioController.ts" />
|
/// <reference path="../../voice/AudioController.ts" />
|
||||||
|
|
||||||
namespace Modals {
|
namespace Modals {
|
||||||
import set = Reflect.set;
|
|
||||||
|
|
||||||
export function spawnSettingsModal() {
|
export function spawnSettingsModal() {
|
||||||
let modal;
|
let modal;
|
||||||
modal = createModal({
|
modal = createModal({
|
||||||
|
@ -59,8 +57,10 @@ namespace Modals {
|
||||||
|
|
||||||
switch (select.value) {
|
switch (select.value) {
|
||||||
case "ppt":
|
case "ppt":
|
||||||
let keyCode: number = parseInt(settings.global("vad_ppt_key", String.fromCharCode(JQuery.Key.T)));
|
let ppt_settings: PPTKeySettings = settings.global('vad_ppt_settings', undefined);
|
||||||
vad_tag.find(".vat_ppt_key").text(String.fromCharCode(keyCode));
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings as any as string) : {};
|
||||||
|
|
||||||
|
vad_tag.find(".vat_ppt_key").text(ppt.key_description(ppt_settings));
|
||||||
break;
|
break;
|
||||||
case "vad":
|
case "vad":
|
||||||
let slider = vad_tag.find(".vad_vad_slider");
|
let slider = vad_tag.find(".vad_vad_slider");
|
||||||
|
@ -88,13 +88,25 @@ namespace Modals {
|
||||||
},
|
},
|
||||||
footer: ""
|
footer: ""
|
||||||
});
|
});
|
||||||
$(document).one("keypress", function (e) {
|
|
||||||
console.log("Got key " + e.keyCode);
|
let listener = (event: ppt.KeyEvent) => {
|
||||||
modal.close();
|
if(event.type == ppt.EventType.KEY_TYPED) {
|
||||||
settings.changeGlobal("vad_ppt_key", e.keyCode.toString());
|
settings.changeGlobal('vad_ppt_key', undefined); //TODO remove that because its legacy shit
|
||||||
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
|
console.log("Got key %o", event);
|
||||||
vad_tag.find(".vat_ppt_key").text(String.fromCharCode(e.keyCode));
|
|
||||||
});
|
let ppt_settings: PPTKeySettings = settings.global('vad_ppt_settings', undefined);
|
||||||
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings as any as string) : {};
|
||||||
|
Object.assign(ppt_settings, event);
|
||||||
|
settings.changeGlobal('vad_ppt_settings', ppt_settings);
|
||||||
|
|
||||||
|
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
|
||||||
|
|
||||||
|
ppt.unregister_key_listener(listener);
|
||||||
|
modal.close();
|
||||||
|
vad_tag.find(".vat_ppt_key").text(ppt.key_description(event));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ppt.register_key_listener(listener);
|
||||||
modal.open();
|
modal.open();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,6 @@
|
||||||
/// <reference path="client.ts" />
|
/// <reference path="client.ts" />
|
||||||
/// <reference path="modal/ModalCreateChannel.ts" />
|
/// <reference path="modal/ModalCreateChannel.ts" />
|
||||||
|
|
||||||
let shift_pressed = false;
|
|
||||||
$(document).on('keyup keydown', function(e){
|
|
||||||
shift_pressed = e.shiftKey;
|
|
||||||
console.log(shift_pressed);
|
|
||||||
});
|
|
||||||
class ChannelTree {
|
class ChannelTree {
|
||||||
client: TSClient;
|
client: TSClient;
|
||||||
htmlTree: JQuery;
|
htmlTree: JQuery;
|
||||||
|
@ -271,8 +266,7 @@ class ChannelTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelect(entry?: ChannelEntry | ClientEntry | ServerEntry, enforce_single?: boolean) {
|
onSelect(entry?: ChannelEntry | ClientEntry | ServerEntry, enforce_single?: boolean) {
|
||||||
console.log(shift_pressed);
|
if(this.currently_selected && ppt.key_pressed(ppt.SpecialKey.SHIFT) && entry instanceof ClientEntry) { //Currently we're only supporting client multiselects :D
|
||||||
if(this.currently_selected && shift_pressed && entry instanceof ClientEntry) { //Currently we're only supporting client multiselects :D
|
|
||||||
if(!entry) return; //Nowhere
|
if(!entry) return; //Nowhere
|
||||||
|
|
||||||
if($.isArray(this.currently_selected)) {
|
if($.isArray(this.currently_selected)) {
|
||||||
|
|
|
@ -120,10 +120,34 @@ class VoiceRecorder {
|
||||||
reinitialiseVAD() {
|
reinitialiseVAD() {
|
||||||
let type = settings.global("vad_type", "vad");
|
let type = settings.global("vad_type", "vad");
|
||||||
if(type == "ppt") {
|
if(type == "ppt") {
|
||||||
let keyCode: number = parseInt(settings.global("vad_ppt_key", String.fromCharCode(JQuery.Key.T)));
|
if(settings.global('vad_ppt_key', undefined)) {
|
||||||
|
//TODO remove that because its legacy shit
|
||||||
|
createErrorModal("VAD changed!", "VAD key detection changed.<br>Please reset your PPT key!").open();
|
||||||
|
}
|
||||||
|
let ppt_settings: PPTKeySettings = settings.global('vad_ppt_settings', undefined);
|
||||||
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings as any as string) : {};
|
||||||
|
|
||||||
|
if(ppt_settings.version === undefined)
|
||||||
|
ppt_settings.version = 1;
|
||||||
|
|
||||||
|
if(ppt_settings.key_code === undefined)
|
||||||
|
ppt_settings.key_code = "KeyT";
|
||||||
|
|
||||||
|
if(ppt_settings.key_ctrl === undefined)
|
||||||
|
ppt_settings.key_ctrl = false;
|
||||||
|
|
||||||
|
if(ppt_settings.key_shift === undefined)
|
||||||
|
ppt_settings.key_shift = false;
|
||||||
|
|
||||||
|
if(ppt_settings.key_alt === undefined)
|
||||||
|
ppt_settings.key_alt = false;
|
||||||
|
|
||||||
|
if(ppt_settings.key_windows === undefined)
|
||||||
|
ppt_settings.key_windows = false;
|
||||||
|
|
||||||
if(!(this.getVADHandler() instanceof PushToTalkVAD))
|
if(!(this.getVADHandler() instanceof PushToTalkVAD))
|
||||||
this.setVADHandler(new PushToTalkVAD(keyCode));
|
this.setVADHandler(new PushToTalkVAD(ppt_settings));
|
||||||
else (this.getVADHandler() as PushToTalkVAD).key = keyCode;
|
else (this.getVADHandler() as PushToTalkVAD).key = ppt_settings;
|
||||||
} else if(type == "pt") {
|
} else if(type == "pt") {
|
||||||
if(!(this.getVADHandler() instanceof PassThroughVAD))
|
if(!(this.getVADHandler() instanceof PassThroughVAD))
|
||||||
this.setVADHandler(new PassThroughVAD());
|
this.setVADHandler(new PassThroughVAD());
|
||||||
|
@ -298,35 +322,36 @@ class VoiceActivityDetectorVAD extends VoiceActivityDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PPTKeySettings extends ppt.KeyDescriptor{
|
||||||
|
version?: number;
|
||||||
|
}
|
||||||
|
|
||||||
class PushToTalkVAD extends VoiceActivityDetector {
|
class PushToTalkVAD extends VoiceActivityDetector {
|
||||||
private _key: number;
|
private _key: ppt.KeyDescriptor;
|
||||||
|
private _key_hook: ppt.KeyHook;
|
||||||
|
|
||||||
private _pushed: boolean = false;
|
private _pushed: boolean = false;
|
||||||
private _evListenerDown = (e: KeyboardEvent) => {
|
|
||||||
//console.log("Down -> " + e.key + " -> " + e.keyCode);
|
|
||||||
if(e.key == String.fromCharCode(this._key))
|
|
||||||
this.pushed = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _evListenerUp = e => {
|
constructor(key: ppt.KeyDescriptor) {
|
||||||
if(e.key == String.fromCharCode(this._key))
|
|
||||||
this.pushed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(key: any) {
|
|
||||||
super();
|
super();
|
||||||
this._key = key;
|
this._key = key;
|
||||||
|
this._key_hook = {
|
||||||
|
callback_release: () => this._pushed = false,
|
||||||
|
callback_press: () => this._pushed = true,
|
||||||
|
|
||||||
|
cancel: false
|
||||||
|
} as ppt.KeyHook;
|
||||||
|
Object.assign(this._key_hook, this._key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
initialise() {
|
initialise() {
|
||||||
document.addEventListener("keydown", this._evListenerDown);
|
ppt.register_key_hook(this._key_hook);
|
||||||
document.addEventListener("keyup", this._evListenerUp);
|
|
||||||
return super.initialise();
|
return super.initialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
finalize() {
|
||||||
document.removeEventListener("keydown", this._evListenerDown);
|
ppt.unregister_key_hook(this._key_hook);
|
||||||
document.removeEventListener("keyup", this._evListenerUp);
|
|
||||||
return super.finalize();
|
return super.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,8 +359,8 @@ class PushToTalkVAD extends VoiceActivityDetector {
|
||||||
this._pushed = flag;
|
this._pushed = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
set key(key: number) {
|
set key(key: ppt.KeyDescriptor) {
|
||||||
this._key = key;
|
Object.assign(this._key_hook, this._key);
|
||||||
this._pushed = false;
|
this._pushed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"js/workers",
|
"shared/js/workers",
|
||||||
"shared/declarations/**/*.d.ts",
|
"shared/declarations/**/*.d.ts",
|
||||||
|
"shared/generated",
|
||||||
"web/declarations/**/*.d.ts",
|
"web/declarations/**/*.d.ts",
|
||||||
|
"web/generated/",
|
||||||
|
"web/environment/",
|
||||||
"vendor/**/*.ts"
|
"vendor/**/*.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,13 +1,133 @@
|
||||||
/// <reference path="../declarations/imports_shared.d.ts"/>
|
/// <reference path="../declarations/imports_shared.d.ts"/>
|
||||||
|
|
||||||
namespace ppt {
|
namespace ppt {
|
||||||
|
interface WebKeyEvent extends KeyEvent {
|
||||||
|
canceled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let key_listener: ((_: KeyEvent) => any)[] = [];
|
||||||
|
|
||||||
|
function listener_key(type: EventType, event: KeyboardEvent) {
|
||||||
|
const key_event = {
|
||||||
|
type: type,
|
||||||
|
|
||||||
|
key: event.key,
|
||||||
|
key_code: event.code,
|
||||||
|
|
||||||
|
key_ctrl: event.ctrlKey,
|
||||||
|
key_shift: event.shiftKey,
|
||||||
|
key_alt: event.altKey,
|
||||||
|
key_windows: event.metaKey,
|
||||||
|
|
||||||
|
canceled: event.defaultPrevented
|
||||||
|
} as WebKeyEvent;
|
||||||
|
//console.debug("Trigger key event %o", key_event);
|
||||||
|
|
||||||
|
for(const listener of key_listener)
|
||||||
|
listener(key_event);
|
||||||
|
|
||||||
|
if(key_event.canceled)
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy_key_press = event => listener_key(EventType.KEY_PRESS, event);
|
||||||
|
const proxy_key_release = event => listener_key(EventType.KEY_RELEASE, event);
|
||||||
|
const proxy_key_typed = event => listener_key(EventType.KEY_TYPED, event);
|
||||||
|
|
||||||
export function initialize() : Promise<void> {
|
export function initialize() : Promise<void> {
|
||||||
|
document.addEventListener('keypress', proxy_key_typed);
|
||||||
|
document.addEventListener('keydown', proxy_key_press);
|
||||||
|
document.addEventListener('keyup', proxy_key_release);
|
||||||
|
|
||||||
|
register_key_listener(listener_hook);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function finalize() {}
|
export function finalize() {
|
||||||
|
document.removeEventListener("keypress", proxy_key_typed);
|
||||||
|
document.removeEventListener("keydown", proxy_key_press);
|
||||||
|
document.removeEventListener("keyup", proxy_key_release);
|
||||||
|
|
||||||
export function register_key_hook(callback: (event: KeyEvent) => any, cancel: boolean) {}
|
unregister_key_listener(listener_hook);
|
||||||
export function unregister_key_hook(callback: (event: KeyEvent) => any) {}
|
}
|
||||||
|
|
||||||
|
export function register_key_listener(listener: (_: KeyEvent) => any) {
|
||||||
|
key_listener.push(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister_key_listener(listener: (_: KeyEvent) => any) {
|
||||||
|
key_listener.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let key_hooks: KeyHook[] = [];
|
||||||
|
|
||||||
|
interface CurrentState {
|
||||||
|
event: KeyEvent;
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
special: { [key:number]:boolean };
|
||||||
|
}
|
||||||
|
let current_state: CurrentState = {
|
||||||
|
special: []
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
let key_hooks_active: KeyHook[] = [];
|
||||||
|
|
||||||
|
function listener_hook(event: KeyEvent) {
|
||||||
|
if(event.type == EventType.KEY_TYPED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let old_hooks = [...key_hooks_active];
|
||||||
|
let new_hooks = [];
|
||||||
|
|
||||||
|
current_state.special[SpecialKey.ALT] = event.key_alt;
|
||||||
|
current_state.special[SpecialKey.CTRL] = event.key_ctrl;
|
||||||
|
current_state.special[SpecialKey.SHIFT] = event.key_shift;
|
||||||
|
current_state.special[SpecialKey.WINDOWS] = event.key_windows;
|
||||||
|
|
||||||
|
current_state.code = undefined;
|
||||||
|
current_state.event = undefined;
|
||||||
|
|
||||||
|
if(event.type == EventType.KEY_PRESS) {
|
||||||
|
current_state.event = event;
|
||||||
|
current_state.code = event.key_code;
|
||||||
|
|
||||||
|
for(const hook of key_hooks) {
|
||||||
|
if(hook.key_code != event.key_code) continue;
|
||||||
|
if(hook.key_alt != event.key_alt) continue;
|
||||||
|
if(hook.key_ctrl != event.key_ctrl) continue;
|
||||||
|
if(hook.key_shift != event.key_shift) continue;
|
||||||
|
if(hook.key_windows != event.key_windows) continue;
|
||||||
|
|
||||||
|
new_hooks.push(hook);
|
||||||
|
if(!old_hooks.remove(hook) && hook.callback_press) {
|
||||||
|
hook.callback_press();
|
||||||
|
console.debug("Trigger key press for %o!", hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//We have a new situation
|
||||||
|
for(const hook of old_hooks)
|
||||||
|
if(hook.callback_release) {
|
||||||
|
hook.callback_release();
|
||||||
|
console.debug("Trigger key release for %o!", hook);
|
||||||
|
}
|
||||||
|
key_hooks_active = new_hooks;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function register_key_hook(hook: KeyHook) {
|
||||||
|
key_hooks.push(hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister_key_hook(hook: KeyHook) {
|
||||||
|
key_hooks.remove(hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function key_pressed(code: string | SpecialKey) : boolean {
|
||||||
|
if(typeof(code) === 'string')
|
||||||
|
return current_state.code == code;
|
||||||
|
return current_state.special[code];
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue