summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go192
1 files changed, 192 insertions, 0 deletions
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)
+}