diff options
Diffstat (limited to 'cmd/magic4linux')
| -rw-r--r-- | cmd/magic4linux/main.go | 171 | 
1 files changed, 171 insertions, 0 deletions
| diff --git a/cmd/magic4linux/main.go b/cmd/magic4linux/main.go new file mode 100644 index 0000000..0275d64 --- /dev/null +++ b/cmd/magic4linux/main.go @@ -0,0 +1,171 @@ +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() + +	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, tp) +			if err != nil { +				log.Printf("connect: %v", err) +			} +		} +	} +} + +func connect(ctx context.Context, dev m4p.DeviceInfo, kbd uinput.Keyboard, 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.Key1 +			case m4p.Key3: +				key = uinput.Key1 +			case m4p.Key4: +				key = uinput.Key1 +			case m4p.Key5: +				key = uinput.Key1 +			case m4p.Key6: +				key = uinput.Key1 +			case m4p.Key7: +				key = uinput.Key1 +			case m4p.Key8: +				key = uinput.Key1 +			case m4p.Key9: +				key = uinput.Key1 +			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) + +		default: +		} +	} +} | 
