summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitrii Morozov <snoopdesigns@gmail.com>2024-03-27 20:38:37 +0100
committerDmitrii Morozov <snoopdesigns@gmail.com>2024-03-27 20:38:37 +0100
commitfd96ce3403f0bf98c215152e0d8424673c9db7e6 (patch)
tree5c5e4d8fb0db544a3d379015d62da09c410e035d
parent89e22871b2e44b374af312d1bf3fdfd83774ce16 (diff)
Refactoring
-rw-r--r--Makefile10
-rw-r--r--cmd/magic4linux/main.go188
-rw-r--r--input/keycodes.go273
-rw-r--r--input/wrapper-empty.go49
-rw-r--r--input/wrapper-uinput.go74
-rw-r--r--input/wrapper.go49
-rw-r--r--main.go192
7 files changed, 647 insertions, 188 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b2f9952
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+BINARY_NAME:=magic4linux
+
+build:
+ GOOS=linux go build -o ${BINARY_NAME} main.go
+
+run: build
+ ./${BINARY_NAME}
+
+clean:
+ go clean \ No newline at end of file
diff --git a/cmd/magic4linux/main.go b/cmd/magic4linux/main.go
deleted file mode 100644
index fa98371..0000000
--- a/cmd/magic4linux/main.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package main
-
-import (
- "bytes"
- "context"
- "encoding/binary"
- "fmt"
- "log"
- "os"
- "os/signal"
- "syscall"
-
- "github.com/bendahl/uinput"
-
- "github.com/mafredri/magic4linux/m4p"
-)
-
-const (
- broadcastPort = 42830
- subscriptionPort = 42831
-)
-
-func main() {
- ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
- defer cancel()
-
- if err := run(ctx); err != nil {
- panic(err)
- }
-}
-
-func run(ctx context.Context) error {
- kbd, err := uinput.CreateKeyboard("/dev/uinput", []byte("magic4linux-keyboard"))
- if err != nil {
- return err
- }
- defer kbd.Close()
-
- mouse, err := uinput.CreateMouse("/dev/uinput", []byte("magic4linux-mouse"))
- if err != nil {
- return err
- }
- defer mouse.Close()
-
- tp, err := uinput.CreateTouchPad("/dev/uinput", []byte("magic4linux-touchpad"), 0, 1920, 0, 1080)
- if err != nil {
- return err
- }
- defer tp.Close()
-
- d, err := m4p.NewDiscoverer(broadcastPort)
- if err != nil {
- return err
- }
- defer d.Close()
-
- for {
- select {
- case <-ctx.Done():
- return nil
-
- case dev := <-d.NextDevice():
- err = connect(ctx, dev, kbd, mouse, tp)
- if err != nil {
- log.Printf("connect: %v", err)
- }
- }
- }
-}
-
-func connect(ctx context.Context, dev m4p.DeviceInfo, kbd uinput.Keyboard, mouse uinput.Mouse, tp uinput.TouchPad) error {
- addr := fmt.Sprintf("%s:%d", dev.IPAddr, dev.Port)
- log.Printf("connect: connecting to: %s", addr)
-
- client, err := m4p.Dial(ctx, addr)
- if err != nil {
- return err
- }
- defer client.Close()
-
- for {
- m, err := client.Recv(ctx)
- if err != nil {
- return err
- }
-
- switch m.Type {
- case m4p.InputMessage:
- log.Printf("connect: got %s: %v", m.Type, m.Input)
-
- // PoC Kodi keyboard mapping.
- key := m.Input.Parameters.KeyCode
- switch key {
- case m4p.KeyWheelPressed:
- key = uinput.KeyEnter
- case m4p.KeyChannelUp:
- key = uinput.KeyPageup
- case m4p.KeyChannelDown:
- key = uinput.KeyPagedown
- case m4p.KeyLeft:
- key = uinput.KeyLeft
- case m4p.KeyUp:
- key = uinput.KeyUp
- case m4p.KeyRight:
- key = uinput.KeyRight
- case m4p.KeyDown:
- key = uinput.KeyDown
- case m4p.Key0:
- key = uinput.Key0
- case m4p.Key1:
- key = uinput.Key1
- case m4p.Key2:
- key = uinput.Key2
- case m4p.Key3:
- key = uinput.Key3
- case m4p.Key4:
- key = uinput.Key4
- case m4p.Key5:
- key = uinput.Key5
- case m4p.Key6:
- key = uinput.Key6
- case m4p.Key7:
- key = uinput.Key7
- case m4p.Key8:
- key = uinput.Key8
- case m4p.Key9:
- key = uinput.Key9
- case m4p.KeyRed:
- key = uinput.KeyStop
- case m4p.KeyGreen:
- key = uinput.KeyPlaypause
- case m4p.KeyYellow:
- key = uinput.KeyZ
- case m4p.KeyBlue:
- key = uinput.KeyC
- case m4p.KeyBack:
- key = uinput.KeyBackspace
- }
-
- if m.Input.Parameters.IsDown {
- kbd.KeyDown(key)
- } else {
- kbd.KeyUp(key)
- }
- case m4p.RemoteUpdateMessage:
- // log.Printf("connect: got %s: %s", m.Type, hex.EncodeToString(m.RemoteUpdate.Payload))
-
- r := bytes.NewReader(m.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", m.Type, err)
- break
- }
- }
-
- x := coordinate[0]
- y := coordinate[1]
- // fmt.Println("Move mouse", x, y)
- tp.MoveTo(x, y)
-
- // log.Printf("connect: %d %d %#v %#v %#v %#v", returnValue, deviceID, coordinate, gyroscope, acceleration, quaternion)
-
- case m4p.MouseMessage:
- switch m.Mouse.Type {
- case "mousedown":
- tp.LeftPress()
- case "mouseup":
- tp.LeftRelease()
- }
-
- case m4p.WheelMessage:
- mouse.Wheel(false, m.Wheel.Delta)
-
- default:
- }
- }
-}
diff --git a/input/keycodes.go b/input/keycodes.go
new file mode 100644
index 0000000..ede83c8
--- /dev/null
+++ b/input/keycodes.go
@@ -0,0 +1,273 @@
+package input
+
+// Inherited from uinput
+const (
+ keyReserved = 0
+ KeyEsc = 1
+ Key1 = 2
+ Key2 = 3
+ Key3 = 4
+ Key4 = 5
+ Key5 = 6
+ Key6 = 7
+ Key7 = 8
+ Key8 = 9
+ Key9 = 10
+ Key0 = 11
+ KeyMinus = 12
+ KeyEqual = 13
+ KeyBackspace = 14
+ KeyTab = 15
+ KeyQ = 16
+ KeyW = 17
+ KeyE = 18
+ KeyR = 19
+ KeyT = 20
+ KeyY = 21
+ KeyU = 22
+ KeyI = 23
+ KeyO = 24
+ KeyP = 25
+ KeyLeftbrace = 26
+ KeyRightbrace = 27
+ KeyEnter = 28
+ KeyLeftctrl = 29
+ KeyA = 30
+ KeyS = 31
+ KeyD = 32
+ KeyF = 33
+ KeyG = 34
+ KeyH = 35
+ KeyJ = 36
+ KeyK = 37
+ KeyL = 38
+ KeySemicolon = 39
+ KeyApostrophe = 40
+ KeyGrave = 41
+ KeyLeftshift = 42
+ KeyBackslash = 43
+ KeyZ = 44
+ KeyX = 45
+ KeyC = 46
+ KeyV = 47
+ KeyB = 48
+ KeyN = 49
+ KeyM = 50
+ KeyComma = 51
+ KeyDot = 52
+ KeySlash = 53
+ KeyRightshift = 54
+ KeyKpasterisk = 55
+ KeyLeftalt = 56
+ KeySpace = 57
+ KeyCapslock = 58
+ KeyF1 = 59
+ KeyF2 = 60
+ KeyF3 = 61
+ KeyF4 = 62
+ KeyF5 = 63
+ KeyF6 = 64
+ KeyF7 = 65
+ KeyF8 = 66
+ KeyF9 = 67
+ KeyF10 = 68
+ KeyNumlock = 69
+ KeyScrolllock = 70
+ KeyKp7 = 71
+ KeyKp8 = 72
+ KeyKp9 = 73
+ KeyKpminus = 74
+ KeyKp4 = 75
+ KeyKp5 = 76
+ KeyKp6 = 77
+ KeyKpplus = 78
+ KeyKp1 = 79
+ KeyKp2 = 80
+ KeyKp3 = 81
+ KeyKp0 = 82
+ KeyKpdot = 83
+ KeyZenkakuhankaku = 85
+ Key102Nd = 86
+ KeyF11 = 87
+ KeyF12 = 88
+ KeyRo = 89
+ KeyKatakana = 90
+ KeyHiragana = 91
+ KeyHenkan = 92
+ KeyKatakanahiragana = 93
+ KeyMuhenkan = 94
+ KeyKpjpcomma = 95
+ KeyKpenter = 96
+ KeyRightctrl = 97
+ KeyKpslash = 98
+ KeySysrq = 99
+ KeyRightalt = 100
+ KeyLinefeed = 101
+ KeyHome = 102
+ KeyUp = 103
+ KeyPageup = 104
+ KeyLeft = 105
+ KeyRight = 106
+ KeyEnd = 107
+ KeyDown = 108
+ KeyPagedown = 109
+ KeyInsert = 110
+ KeyDelete = 111
+ KeyMacro = 112
+ KeyMute = 113
+ KeyVolumedown = 114
+ KeyVolumeup = 115
+ KeyPower = 116 /*ScSystemPowerDown*/
+ KeyKpequal = 117
+ KeyKpplusminus = 118
+ KeyPause = 119
+ KeyScale = 120 /*AlCompizScale(Expose)*/
+ KeyKpcomma = 121
+ KeyHangeul = 122
+ KeyHanja = 123
+ KeyYen = 124
+ KeyLeftmeta = 125
+ KeyRightmeta = 126
+ KeyCompose = 127
+ KeyStop = 128 /*AcStop*/
+ KeyAgain = 129
+ KeyProps = 130 /*AcProperties*/
+ KeyUndo = 131 /*AcUndo*/
+ KeyFront = 132
+ KeyCopy = 133 /*AcCopy*/
+ KeyOpen = 134 /*AcOpen*/
+ KeyPaste = 135 /*AcPaste*/
+ KeyFind = 136 /*AcSearch*/
+ KeyCut = 137 /*AcCut*/
+ KeyHelp = 138 /*AlIntegratedHelpCenter*/
+ KeyMenu = 139 /*Menu(ShowMenu)*/
+ KeyCalc = 140 /*AlCalculator*/
+ KeySetup = 141
+ KeySleep = 142 /*ScSystemSleep*/
+ KeyWakeup = 143 /*SystemWakeUp*/
+ KeyFile = 144 /*AlLocalMachineBrowser*/
+ KeySendfile = 145
+ KeyDeletefile = 146
+ KeyXfer = 147
+ KeyProg1 = 148
+ KeyProg2 = 149
+ KeyWww = 150 /*AlInternetBrowser*/
+ KeyMsdos = 151
+ KeyCoffee = 152 /*AlTerminalLock/Screensaver*/
+ KeyDirection = 153
+ KeyCyclewindows = 154
+ KeyMail = 155
+ KeyBookmarks = 156 /*AcBookmarks*/
+ KeyComputer = 157
+ KeyBack = 158 /*AcBack*/
+ KeyForward = 159 /*AcForward*/
+ KeyClosecd = 160
+ KeyEjectcd = 161
+ KeyEjectclosecd = 162
+ KeyNextsong = 163
+ KeyPlaypause = 164
+ KeyPrevioussong = 165
+ KeyStopcd = 166
+ KeyRecord = 167
+ KeyRewind = 168
+ KeyPhone = 169 /*MediaSelectTelephone*/
+ KeyIso = 170
+ KeyConfig = 171 /*AlConsumerControlConfiguration*/
+ KeyHomepage = 172 /*AcHome*/
+ KeyRefresh = 173 /*AcRefresh*/
+ KeyExit = 174 /*AcExit*/
+ KeyMove = 175
+ KeyEdit = 176
+ KeyScrollup = 177
+ KeyScrolldown = 178
+ KeyKpleftparen = 179
+ KeyKprightparen = 180
+ KeyNew = 181 /*AcNew*/
+ KeyRedo = 182 /*AcRedo/Repeat*/
+ KeyF13 = 183
+ KeyF14 = 184
+ KeyF15 = 185
+ KeyF16 = 186
+ KeyF17 = 187
+ KeyF18 = 188
+ KeyF19 = 189
+ KeyF20 = 190
+ KeyF21 = 191
+ KeyF22 = 192
+ KeyF23 = 193
+ KeyF24 = 194
+ KeyPlaycd = 200
+ KeyPausecd = 201
+ KeyProg3 = 202
+ KeyProg4 = 203
+ KeyDashboard = 204 /*AlDashboard*/
+ KeySuspend = 205
+ KeyClose = 206 /*AcClose*/
+ KeyPlay = 207
+ KeyFastforward = 208
+ KeyBassboost = 209
+ KeyPrint = 210 /*AcPrint*/
+ KeyHp = 211
+ KeyCamera = 212
+ KeySound = 213
+ KeyQuestion = 214
+ KeyEmail = 215
+ KeyChat = 216
+ KeySearch = 217
+ KeyConnect = 218
+ KeyFinance = 219 /*AlCheckbook/Finance*/
+ KeySport = 220
+ KeyShop = 221
+ KeyAlterase = 222
+ KeyCancel = 223 /*AcCancel*/
+ KeyBrightnessdown = 224
+ KeyBrightnessup = 225
+ KeyMedia = 226
+ KeySwitchvideomode = 227 /*CycleBetweenAvailableVideo */
+ KeyKbdillumtoggle = 228
+ KeyKbdillumdown = 229
+ KeyKbdillumup = 230
+ KeySend = 231 /*AcSend*/
+ KeyReply = 232 /*AcReply*/
+ KeyForwardmail = 233 /*AcForwardMsg*/
+ KeySave = 234 /*AcSave*/
+ KeyDocuments = 235
+ KeyBattery = 236
+ KeyBluetooth = 237
+ KeyWlan = 238
+ KeyUwb = 239
+ KeyUnknown = 240
+ KeyVideoNext = 241 /*DriveNextVideoSource*/
+ KeyVideoPrev = 242 /*DrivePreviousVideoSource*/
+ KeyBrightnessCycle = 243 /*BrightnessUp,AfterMaxIsMin*/
+ KeyBrightnessZero = 244 /*BrightnessOff,UseAmbient*/
+ KeyDisplayOff = 245 /*DisplayDeviceToOffState*/
+ KeyWimax = 246
+ KeyRfkill = 247 /*KeyThatControlsAllRadios*/
+ KeyMicmute = 248 /*Mute/UnmuteTheMicrophone*/
+ keyMax = 248 // highest key currently defined in this keyboard api
+
+ ButtonGamepad = 0x130
+
+ ButtonSouth = 0x130 // A / X
+ ButtonEast = 0x131 // X / Square
+ ButtonNorth = 0x133 // Y / Triangle
+ ButtonWest = 0x134 // B / Circle
+
+ ButtonBumperLeft = 0x136 // L1
+ ButtonBumperRight = 0x137 // R1
+ ButtonTriggerLeft = 0x138 // L2
+ ButtonTriggerRight = 0x139 // R2
+ ButtonThumbLeft = 0x13d // L3
+ ButtonThumbRight = 0x13e // R3
+
+ ButtonSelect = 0x13a
+ ButtonStart = 0x13b
+
+ ButtonDpadUp = 0x220
+ ButtonDpadDown = 0x221
+ ButtonDpadLeft = 0x222
+ ButtonDpadRight = 0x223
+
+ ButtonMode = 0x13c // This is the special button that usually bears the Xbox or Playstation logo
+)
diff --git a/input/wrapper-empty.go b/input/wrapper-empty.go
new file mode 100644
index 0000000..5459a20
--- /dev/null
+++ b/input/wrapper-empty.go
@@ -0,0 +1,49 @@
+package input
+
+import (
+ "fmt"
+)
+
+type KeyboardEmptyWrapper struct {
+}
+
+type MouseEmptyWrapper struct {
+}
+
+func (mockKeyboard KeyboardEmptyWrapper) KeyDown(key int) error {
+ fmt.Println("Key down")
+ return nil
+}
+
+func (mockKeyboard KeyboardEmptyWrapper) KeyUp(key int) error {
+ fmt.Println("Key up")
+ return nil
+}
+
+func (mockKeyboard KeyboardEmptyWrapper) Close() error {
+ return nil
+}
+
+func (mockMouse MouseEmptyWrapper) Move(x, y int32) error {
+ //fmt.Println("Move")
+ return nil
+}
+
+func (mockMouse MouseEmptyWrapper) LeftPress() error {
+ fmt.Println("Left press")
+ return nil
+}
+
+func (mockMouse MouseEmptyWrapper) LeftRelease() error {
+ fmt.Println("Left release")
+ return nil
+}
+
+func (mockMouse MouseEmptyWrapper) Wheel(horizontal bool, delta int32) error {
+ fmt.Println("Wheel")
+ return nil
+}
+
+func (mockMouse MouseEmptyWrapper) Close() error {
+ return nil
+}
diff --git a/input/wrapper-uinput.go b/input/wrapper-uinput.go
new file mode 100644
index 0000000..26877f2
--- /dev/null
+++ b/input/wrapper-uinput.go
@@ -0,0 +1,74 @@
+package input
+
+import (
+ "fmt"
+
+ "github.com/bendahl/uinput"
+)
+
+type KeyboardUinputWrapper struct {
+ keyboard uinput.Keyboard
+}
+
+type MouseUinputWrapper struct {
+ mouse uinput.Mouse
+ touchpad uinput.TouchPad
+}
+
+func (uinputKeyboard *KeyboardUinputWrapper) Init() error {
+ kbd, err := uinput.CreateKeyboard("/dev/uinput", []byte("magic4linux-keyboard"))
+ if err != nil {
+ panic(err)
+ }
+ uinputKeyboard.keyboard = kbd
+ return nil
+}
+
+func (uinputMouse *MouseUinputWrapper) Init() error {
+ mouse, err := uinput.CreateMouse("/dev/uinput", []byte("magic4linux-mouse"))
+ if err != nil {
+ panic(err)
+ }
+ uinputMouse.mouse = mouse
+
+ // TODO resolution
+ tp, err := uinput.CreateTouchPad("/dev/uinput", []byte("magic4linux-touchpad"), 0, 1920, 0, 1080)
+ if err != nil {
+ panic(err)
+ }
+ uinputMouse.touchpad = tp
+ return nil
+}
+
+func (uinputKeyboard KeyboardUinputWrapper) KeyDown(key int) error {
+ return uinputKeyboard.keyboard.KeyDown(key)
+}
+
+func (uinputKeyboard KeyboardUinputWrapper) KeyUp(key int) error {
+ return uinputKeyboard.keyboard.KeyUp(key)
+}
+
+func (uinputKeyboard KeyboardUinputWrapper) Close() error {
+ return uinputKeyboard.keyboard.Close()
+}
+
+func (uinputMouse MouseUinputWrapper) Move(x, y int32) error {
+ return uinputMouse.touchpad.MoveTo(x, y)
+}
+
+func (uinputMouse MouseUinputWrapper) LeftPress() error {
+ fmt.Println("Left!!!!")
+ return uinputMouse.mouse.LeftPress()
+}
+
+func (uinputMouse MouseUinputWrapper) LeftRelease() error {
+ return uinputMouse.mouse.LeftRelease()
+}
+
+func (uinputMouse MouseUinputWrapper) Wheel(horizontal bool, delta int32) error {
+ return uinputMouse.mouse.Wheel(horizontal, delta)
+}
+
+func (uinputMouse MouseUinputWrapper) Close() error {
+ return uinputMouse.mouse.Close()
+}
diff --git a/input/wrapper.go b/input/wrapper.go
new file mode 100644
index 0000000..d194f20
--- /dev/null
+++ b/input/wrapper.go
@@ -0,0 +1,49 @@
+package input
+
+import (
+ "fmt"
+ "io"
+)
+
+const (
+ InputType_debug int = 0
+ InputType_uinput int = 1
+)
+
+type Keyboard interface {
+ KeyDown(key int) error
+ KeyUp(key int) error
+ io.Closer
+}
+
+type Mouse interface {
+ Move(x, y int32) error
+ LeftPress() error
+ LeftRelease() error
+ Wheel(horizontal bool, delta int32) error
+ io.Closer
+}
+
+func CreateKeyboard(inputType int) (Keyboard, error) {
+ switch inputType {
+ case InputType_debug:
+ return KeyboardEmptyWrapper{}, nil
+ case InputType_uinput:
+ uinputKeyboard := new(KeyboardUinputWrapper)
+ uinputKeyboard.Init()
+ return uinputKeyboard, nil
+ }
+ return nil, fmt.Errorf("Unknown inputType: %d", inputType)
+}
+
+func CreateMouse(inputType int) (Mouse, error) {
+ switch inputType {
+ case InputType_debug:
+ return MouseEmptyWrapper{}, nil
+ case InputType_uinput:
+ uinputMouse := new(MouseUinputWrapper)
+ uinputMouse.Init()
+ return uinputMouse, nil
+ }
+ return nil, fmt.Errorf("Unknown inputType: %d", inputType)
+}
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)
+}