diff --git a/frontend/src/lib/input.ts b/frontend/src/lib/input.ts new file mode 100644 index 0000000..7e1fb3b --- /dev/null +++ b/frontend/src/lib/input.ts @@ -0,0 +1,152 @@ +import { Input } from "$lib/proto/input-event" +import { InputEvent } from "$lib/proto/input" +import { Builder } from "flatbuffers"; + +export enum KeyAction { + DOWN, + UP, +} + +export async function sendKeyboardEvent( + writer: WritableStreamDefaultWriter, + event: KeyboardEvent, + keyAction: KeyAction, +) { + const builder = new Builder(1024); + + InputEvent.KeyboardInput.startKeyboardInput(builder); + // Have to use keyCode even though it's deprecated beacuse .code is a unhelpful string :sigh: + InputEvent.KeyboardInput.addKeyCode(builder, event.keyCode); + InputEvent.KeyboardInput.addKeyAction(builder, keyAction); + const modifierState = InputEvent.ModifierState.createModifierState( + builder, + event.shiftKey, + event.ctrlKey, + event.altKey, + event.metaKey + ); + + InputEvent.KeyboardInput.addModifiers(builder, modifierState); + const keyboardInput = InputEvent.KeyboardInput.endKeyboardInput(builder); + + // Create InputEvent table with union + InputEvent.InputEvent.startInputEvent(builder); + InputEvent.InputEvent.addInputType(builder, Input.Keyboard); + InputEvent.InputEvent.addInput(builder, keyboardInput); + const inputEvent = InputEvent.InputEvent.endInputEvent(builder); + + // Finish the buffer + builder.finish(inputEvent); + + // Get the buffer data + const bufferData = builder.asUint8Array(); + + // Create size prefix as big-endian u32 + const sizePrefix = new Uint8Array(4); + const size = bufferData.length; + sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte + sizePrefix[1] = (size >> 16) & 0xFF; + sizePrefix[2] = (size >> 8) & 0xFF; + sizePrefix[3] = size & 0xFF; // Least significant byte + + // Create combined buffer with size prefix + flatbuffer data + const combined = new Uint8Array(sizePrefix.length + bufferData.length); + combined.set(sizePrefix, 0); + combined.set(bufferData, sizePrefix.length); + + // Write to stream + await writer.write(combined); +} + +export async function sendMouseMoveEvent( + writer: WritableStreamDefaultWriter, + event: MouseEvent, +) { + const builder = new Builder(1024); + + const mouseMovement = InputEvent.MouseMovement.createMouseMovement(builder, event.movementX, event.movementY); + + // Create InputEvent table with union + InputEvent.InputEvent.startInputEvent(builder); + InputEvent.InputEvent.addInputType(builder, Input.MouseMovement); + InputEvent.InputEvent.addInput(builder, mouseMovement); + const inputEvent = InputEvent.InputEvent.endInputEvent(builder); + + // Finish the buffer + builder.finish(inputEvent); + + // Get the buffer data + const bufferData = builder.asUint8Array(); + + // Create size prefix as big-endian u32 + const sizePrefix = new Uint8Array(4); + const size = bufferData.length; + sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte + sizePrefix[1] = (size >> 16) & 0xFF; + sizePrefix[2] = (size >> 8) & 0xFF; + sizePrefix[3] = size & 0xFF; // Least significant byte + + // Create combined buffer with size prefix + flatbuffer data + const combined = new Uint8Array(sizePrefix.length + bufferData.length); + combined.set(sizePrefix, 0); + combined.set(bufferData, sizePrefix.length); + + // Write to stream + await writer.write(combined); +} + +export async function sendMouseInputEvent( + writer: WritableStreamDefaultWriter, + event: MouseEvent, + keyAction: KeyAction, +) { + const builder = new Builder(1024); + + var mouseButton: InputEvent.MouseButton; + + switch (event.button) { + case 0: + mouseButton = InputEvent.MouseButton.LEFT; + break; + case 1: + mouseButton = InputEvent.MouseButton.MIDDLE; + break; + case 2: + mouseButton = InputEvent.MouseButton.RIGHT; + break; + default: + console.log(`Unknown mouse button ${event.button}, defaulting to LEFT`); + mouseButton = InputEvent.MouseButton.LEFT; + break; + } + + const mouseInput = InputEvent.MouseInput.createMouseInput(builder, mouseButton, keyAction); + + // Create InputEvent table with union + InputEvent.InputEvent.startInputEvent(builder); + InputEvent.InputEvent.addInputType(builder, Input.MouseInput); + InputEvent.InputEvent.addInput(builder, mouseInput); + const inputEvent = InputEvent.InputEvent.endInputEvent(builder); + + // Finish the buffer + builder.finish(inputEvent); + + // Get the buffer data + const bufferData = builder.asUint8Array(); + + // Create size prefix as big-endian u32 + const sizePrefix = new Uint8Array(4); + const size = bufferData.length; + sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte + sizePrefix[1] = (size >> 16) & 0xFF; + sizePrefix[2] = (size >> 8) & 0xFF; + sizePrefix[3] = size & 0xFF; // Least significant byte + + // Create combined buffer with size prefix + flatbuffer data + const combined = new Uint8Array(sizePrefix.length + bufferData.length); + combined.set(sizePrefix, 0); + combined.set(bufferData, sizePrefix.length); + + // Write to stream + await writer.write(combined); +} diff --git a/frontend/src/routes/stream/stream.ts b/frontend/src/routes/stream/stream.ts index abafcd3..5acd2dc 100644 --- a/frontend/src/routes/stream/stream.ts +++ b/frontend/src/routes/stream/stream.ts @@ -1,6 +1,4 @@ -import { Input } from "$lib/proto/input-event" -import { InputEvent } from "../../lib/proto/input" -import { Builder } from "flatbuffers" +import { sendKeyboardEvent, sendMouseInputEvent, sendMouseMoveEvent, KeyAction } from "$lib/input" type Setup = { video_format: string, @@ -173,154 +171,7 @@ export async function streamVideoFromReader(reader: ReadableStreamDefaultReader, } } -enum KeyAction { - DOWN, - UP, -} -async function sendKeyboardEvent( - writer: WritableStreamDefaultWriter, - event: KeyboardEvent, - keyAction: KeyAction, -) { - const builder = new Builder(1024); - - InputEvent.KeyboardInput.startKeyboardInput(builder); - // Have to use keyCode even though it's deprecated beacuse .code is a unhelpful string :sigh: - InputEvent.KeyboardInput.addKeyCode(builder, event.keyCode); - InputEvent.KeyboardInput.addKeyAction(builder, keyAction); - const modifierState = InputEvent.ModifierState.createModifierState( - builder, - event.shiftKey, - event.ctrlKey, - event.altKey, - event.metaKey - ); - - InputEvent.KeyboardInput.addModifiers(builder, modifierState); - const keyboardInput = InputEvent.KeyboardInput.endKeyboardInput(builder); - - // Create InputEvent table with union - InputEvent.InputEvent.startInputEvent(builder); - InputEvent.InputEvent.addInputType(builder, Input.Keyboard); - InputEvent.InputEvent.addInput(builder, keyboardInput); - const inputEvent = InputEvent.InputEvent.endInputEvent(builder); - - // Finish the buffer - builder.finish(inputEvent); - - // Get the buffer data - const bufferData = builder.asUint8Array(); - - // Create size prefix as big-endian u32 - const sizePrefix = new Uint8Array(4); - const size = bufferData.length; - sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte - sizePrefix[1] = (size >> 16) & 0xFF; - sizePrefix[2] = (size >> 8) & 0xFF; - sizePrefix[3] = size & 0xFF; // Least significant byte - - // Create combined buffer with size prefix + flatbuffer data - const combined = new Uint8Array(sizePrefix.length + bufferData.length); - combined.set(sizePrefix, 0); - combined.set(bufferData, sizePrefix.length); - - // Write to stream - await writer.write(combined); -} - -async function sendMouseMoveEvent( - writer: WritableStreamDefaultWriter, - event: MouseEvent, -) { - const builder = new Builder(1024); - - const mouseMovement = InputEvent.MouseMovement.createMouseMovement(builder, event.movementX, event.movementY); - - // Create InputEvent table with union - InputEvent.InputEvent.startInputEvent(builder); - InputEvent.InputEvent.addInputType(builder, Input.MouseMovement); - InputEvent.InputEvent.addInput(builder, mouseMovement); - const inputEvent = InputEvent.InputEvent.endInputEvent(builder); - - // Finish the buffer - builder.finish(inputEvent); - - // Get the buffer data - const bufferData = builder.asUint8Array(); - - // Create size prefix as big-endian u32 - const sizePrefix = new Uint8Array(4); - const size = bufferData.length; - sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte - sizePrefix[1] = (size >> 16) & 0xFF; - sizePrefix[2] = (size >> 8) & 0xFF; - sizePrefix[3] = size & 0xFF; // Least significant byte - - // Create combined buffer with size prefix + flatbuffer data - const combined = new Uint8Array(sizePrefix.length + bufferData.length); - combined.set(sizePrefix, 0); - combined.set(bufferData, sizePrefix.length); - - // Write to stream - await writer.write(combined); -} - -async function sendMouseInputEvent( - writer: WritableStreamDefaultWriter, - event: MouseEvent, - keyAction: KeyAction, -) { - const builder = new Builder(1024); - - var mouseButton: InputEvent.MouseButton; - - switch (event.button) { - case 0: - mouseButton = InputEvent.MouseButton.LEFT; - break; - case 1: - mouseButton = InputEvent.MouseButton.MIDDLE; - break; - case 2: - mouseButton = InputEvent.MouseButton.RIGHT; - break; - default: - console.log(`Unknown mouse button ${event.button}, defaulting to LEFT`); - mouseButton = InputEvent.MouseButton.LEFT; - break; - } - - const mouseInput = InputEvent.MouseInput.createMouseInput(builder, mouseButton, keyAction); - - // Create InputEvent table with union - InputEvent.InputEvent.startInputEvent(builder); - InputEvent.InputEvent.addInputType(builder, Input.MouseInput); - InputEvent.InputEvent.addInput(builder, mouseInput); - const inputEvent = InputEvent.InputEvent.endInputEvent(builder); - - // Finish the buffer - builder.finish(inputEvent); - - // Get the buffer data - const bufferData = builder.asUint8Array(); - - // Create size prefix as big-endian u32 - const sizePrefix = new Uint8Array(4); - const size = bufferData.length; - sizePrefix[0] = (size >> 24) & 0xFF; // Most significant byte - sizePrefix[1] = (size >> 16) & 0xFF; - sizePrefix[2] = (size >> 8) & 0xFF; - sizePrefix[3] = size & 0xFF; // Least significant byte - - // Create combined buffer with size prefix + flatbuffer data - const combined = new Uint8Array(sizePrefix.length + bufferData.length); - combined.set(sizePrefix, 0); - combined.set(bufferData, sizePrefix.length); - - // Write to stream - await writer.write(combined); -}