From d0d8330191be40ee80341460362f7d1a3d5d6a70 Mon Sep 17 00:00:00 2001 From: datalore Date: Mon, 4 Aug 2025 21:00:18 +0200 Subject: [PATCH] feat(config): Added config.yaml support --- config.go | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ config.yaml | 13 +++++ controller.go | 8 +++ go.mod | 1 + go.sum | 2 + main.go | 9 +-- 6 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 config.go create mode 100644 config.yaml diff --git a/config.go b/config.go new file mode 100644 index 0000000..fd185b3 --- /dev/null +++ b/config.go @@ -0,0 +1,148 @@ +package main + +import ( + "fmt" + "os" + + "github.com/goccy/go-yaml" + "github.com/bendahl/uinput" +) + +type Config struct { + Controller []ControllerConfig +} + +type ControllerConfig struct { + PortName string + VendorID uint16 + ProductID uint16 + Mappings []MappingConfig +} + +type MappingConfig struct { + Comment string + Type MappingType + MidiChannel uint8 + MidiKey uint8 + MidiController uint8 + Button ButtonName + Axis AxisName + IsSigned bool +} + +type MappingType string +type ButtonName string +type AxisName string + +const ( + ButtonMappingType MappingType = "button" + ControlMappingType MappingType = "control" + ButtonNorth ButtonName = "north" + ButtonEast ButtonName = "east" + ButtonSouth ButtonName = "south" + ButtonWest ButtonName = "west" + AxisLeftX AxisName = "left-x" + AxisLeftY AxisName = "left-y" + AxisRightX AxisName = "right-x" + AxisRightY AxisName = "right-y" +) + +func ParseConfig(path string) (Config, error) { + var config Config + + buffer, err := os.ReadFile(path) + if err != nil { + return config, err + } + + err = yaml.Unmarshal(buffer, &config) + if err != nil { + return config, err + } + + return config, nil +} + +func (config Config) Construct() (ControllerList, error) { + var controllerList ControllerList + + for _, controllerConfig := range config.Controller { + actualController, err := controllerConfig.Construct() + if err != nil { + return nil, err + } + + controllerList = append(controllerList, actualController) + } + + return controllerList, nil +} + +func (cc ControllerConfig) Construct() (*Controller, error) { + actualController, err := NewController(cc.PortName, cc.VendorID, cc.ProductID) + if err != nil { + return actualController, err + } + + for _, mappingConfig := range cc.Mappings { + actualMapping, err := mappingConfig.Construct() + if err != nil { + return nil, err + } + + actualController.AddMapping(actualMapping) + } + + return actualController, nil +} + +func (mc MappingConfig) Construct() (Mapping, error) { + switch mc.Type { + case ButtonMappingType: + button, err := mc.Button.Construct() + if err != nil { + return ButtonMapping{}, err + } + + return ButtonMapping{mc.Comment, mc.MidiChannel, mc.MidiKey, button}, nil + case ControlMappingType: + axis, err := mc.Axis.Construct() + if err != nil { + return ControlMapping{}, err + } + + return ControlMapping{mc.Comment, mc.MidiChannel, mc.MidiController, axis, mc.IsSigned}, nil + default: + return ButtonMapping{}, fmt.Errorf("Invalid mapping type") + } +} + +func (bn ButtonName) Construct() (int, error) { + switch bn { + case ButtonNorth: + return uinput.ButtonNorth, nil + case ButtonEast: + return uinput.ButtonEast, nil + case ButtonSouth: + return uinput.ButtonSouth, nil + case ButtonWest: + return uinput.ButtonWest, nil + default: + return -1, fmt.Errorf("Invalid button name") + } +} + +func (an AxisName) Construct() (ControllerAxis, error) { + switch an { + case AxisLeftX: + return LeftX, nil + case AxisLeftY: + return LeftY, nil + case AxisRightX: + return RightX, nil + case AxisRightY: + return RightY, nil + default: + return -1, fmt.Errorf("Invalid axis name") + } +} diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..6b9c6b6 --- /dev/null +++ b/config.yaml @@ -0,0 +1,13 @@ +controller: + - portName: DJControl Inpulse 500 MIDI 1 + vendorID: 0x45e + productID: 0x285 + mappings: + - type: button + midiChannel: 1 + midiKey: 7 + key: south + - type: control + midiChannel: 1 + midiController: 0 + axis: left-y diff --git a/controller.go b/controller.go index d2f95ce..6d2fc68 100644 --- a/controller.go +++ b/controller.go @@ -7,6 +7,14 @@ import ( "github.com/bendahl/uinput" ) +type ControllerList []*Controller + +func (cl ControllerList) Stop() { + for _, controller := range cl { + controller.Stop() + } +} + type Controller struct { midiInput *MidiInput mappings []Mapping diff --git a/go.mod b/go.mod index 9bc0c4c..f65036e 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.24.5 require ( github.com/bendahl/uinput v1.7.0 + github.com/goccy/go-yaml v1.18.0 gitlab.com/gomidi/midi/v2 v2.3.16 ) diff --git a/go.sum b/go.sum index 988e0f3..e6c8a8a 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ github.com/bendahl/uinput v1.7.0 h1:nA4fm8Wu8UYNOPykIZm66nkWEyvxzfmJ8YC02PM40jg= github.com/bendahl/uinput v1.7.0/go.mod h1:Np7w3DINc9wB83p12fTAM3DPPhFnAKP0WTXRqCQJ6Z8= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= gitlab.com/gomidi/midi/v2 v2.3.16 h1:yufWSENyjnJ4LFQa9BerzUm4E4aLfTyzw5nmnCteO0c= gitlab.com/gomidi/midi/v2 v2.3.16/go.mod h1:jDpP4O4skYi+7iVwt6Zyp18bd2M4hkjtMuw2cmgKgfw= diff --git a/main.go b/main.go index bea6fca..402ce0e 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "time" "gitlab.com/gomidi/midi/v2" - "github.com/bendahl/uinput" ) func must[T any](obj T, err error) T { @@ -20,11 +19,9 @@ func main() { defer midi.CloseDriver() log.Println("Starting...") - controller := must(NewController("DJControl Inpulse 500 MIDI 1", 0x45e, 0x285)) // mimics xbox 360 controller - defer controller.Stop() - - controller.AddMapping(ButtonMapping{"Play left", 1, 7, uinput.ButtonSouth}) - controller.AddMapping(ControlMapping{"Volume left", 1, 0, LeftY, false}) + config := must(ParseConfig("config.yaml")) + controllerList := must(config.Construct()) + defer controllerList.Stop() time.Sleep(time.Second * 20) }