From fd96ce3403f0bf98c215152e0d8424673c9db7e6 Mon Sep 17 00:00:00 2001 From: Dmitrii Morozov Date: Wed, 27 Mar 2024 20:38:37 +0100 Subject: Refactoring --- main.go | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 main.go (limited to 'main.go') diff --git a/main.go b/main.go new file mode 100644 index 0000000..fad8c98 --- /dev/null +++ b/main.go @@ -0,0 +1,192 @@ +package main + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "log" + "os" + "os/signal" + "syscall" + + "github.com/mafredri/magic4linux/input" + "github.com/mafredri/magic4linux/m4p" +) + +const ( + broadcastPort = 42830 +) + +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer cancel() + + if err := run(ctx); err != nil { + panic(err) + } +} + +func createInputs() (input.Keyboard, input.Mouse) { + keyboard, err := input.CreateKeyboard(input.InputType_uinput) + if err != nil { + panic(err) + } + + mouse, err := input.CreateMouse(input.InputType_uinput) + if err != nil { + panic(err) + } + + return keyboard, mouse +} + +func discoverer() *m4p.Discoverer { + discoverer, err := m4p.NewDiscoverer(broadcastPort) + if err != nil { + panic(err) + } + return discoverer +} + +func run(ctx context.Context) error { + keyboard, mouse := createInputs() + discoverer := discoverer() + + defer discoverer.Close() + defer keyboard.Close() + defer mouse.Close() + + for { + select { + + case <-ctx.Done(): + return nil + + case device := <-discoverer.NextDevice(): + err := process(ctx, device, keyboard, mouse) + if err != nil { + log.Printf("Process failed with error: %v", err) + } + } + } +} + +func process(ctx context.Context, dev m4p.DeviceInfo, keyboard input.Keyboard, mouse input.Mouse) error { + addr := fmt.Sprintf("%s:%d", dev.IPAddr, dev.Port) + log.Printf("Starting processing with: %s", addr) + + client, err := m4p.Dial(ctx, addr) + if err != nil { + return err + } + defer client.Close() + + for { + message, err := client.Recv(ctx) + if err != nil { + return err + } + + switch message.Type { + case m4p.InputMessage: + processKey(message, keyboard) + case m4p.RemoteUpdateMessage: + processMouseMove(message, mouse) + case m4p.MouseMessage: + processMouseButtons(message, mouse) + case m4p.WheelMessage: + processMouseWheel(message, mouse) + + default: + } + } +} + +func processKey(message m4p.Message, keyboard input.Keyboard) { + key := message.Input.Parameters.KeyCode + switch key { + case m4p.KeyChannelUp: + key = input.KeyPageup + case m4p.KeyChannelDown: + key = input.KeyPagedown + case m4p.KeyLeft: + key = input.KeyLeft + case m4p.KeyUp: + key = input.KeyUp + case m4p.KeyRight: + key = input.KeyRight + case m4p.KeyDown: + key = input.KeyDown + case m4p.Key0: + key = input.Key0 + case m4p.Key1: + key = input.Key1 + case m4p.Key2: + key = input.Key2 + case m4p.Key3: + key = input.Key3 + case m4p.Key4: + key = input.Key4 + case m4p.Key5: + key = input.Key5 + case m4p.Key6: + key = input.Key6 + case m4p.Key7: + key = input.Key7 + case m4p.Key8: + key = input.Key8 + case m4p.Key9: + key = input.Key9 + case m4p.KeyRed: + key = input.KeyStop + case m4p.KeyGreen: + key = input.KeyPlaypause + case m4p.KeyBack: + key = input.KeyBackspace + } + + if message.Input.Parameters.IsDown { + keyboard.KeyDown(key) + } else { + keyboard.KeyUp(key) + } +} + +func processMouseButtons(message m4p.Message, mouse input.Mouse) { + switch message.Mouse.Type { + case "mousedown": + mouse.LeftPress() + case "mouseup": + mouse.LeftRelease() + } +} + +func processMouseWheel(message m4p.Message, mouse input.Mouse) { + mouse.Wheel(false, message.Wheel.Delta/100) +} + +func processMouseMove(message m4p.Message, mouse input.Mouse) { + r := bytes.NewReader(message.RemoteUpdate.Payload) + var returnValue, deviceID uint8 + var coordinate [2]int32 + var gyroscope, acceleration [3]float32 + var quaternion [4]float32 + for _, fn := range []func() error{ + func() error { return binary.Read(r, binary.LittleEndian, &returnValue) }, + func() error { return binary.Read(r, binary.LittleEndian, &deviceID) }, + func() error { return binary.Read(r, binary.LittleEndian, coordinate[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, gyroscope[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, acceleration[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, quaternion[:]) }, + } { + if err := fn(); err != nil { + log.Printf("connect: %s decode failed: %v", message.Type, err) + break + } + } + + x := coordinate[0] + y := coordinate[1] + mouse.Move(x, y) +} -- cgit v1.2.3