package main import ( "fmt" "os" "github.com/goccy/go-yaml" "github.com/bendahl/uinput" ) type Config struct { Controller []ControllerConfig `yaml:"controller"` } type ControllerConfig struct { PortName string `yaml:"portName"` VendorID uint16 `yaml:"vendorID"` ProductID uint16 `yaml:"productID"` Mappings []MappingConfig `yaml:"mappings"` } type MappingConfig struct { Comment string `yaml:"comment"` Type MappingType `yaml:"type"` MidiChannel uint8 `yaml:"midiChannel"` MidiKey uint8 `yaml:"midiKey"` MidiController uint8 `yaml:"midiController"` Button ButtonName `yaml:"button"` Axis AxisName `yaml:"axis"` IsSigned bool `yaml:"isSigned"` } 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" ButtonL1 ButtonName = "l1" ButtonL2 ButtonName = "l2" ButtonL3 ButtonName = "l3" ButtonR1 ButtonName = "r1" ButtonR2 ButtonName = "r2" ButtonR3 ButtonName = "r3" ButtonSelect ButtonName = "select" ButtonStart ButtonName = "start" ButtonDpadUp ButtonName = "dpad-up" ButtonDpadDown ButtonName = "dpad-down" ButtonDpadLeft ButtonName = "dpad-left" ButtonDpadRight ButtonName = "dpad-right" 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(os.ExpandEnv(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 case ButtonL1: return uinput.ButtonBumperLeft, nil case ButtonL2: return uinput.ButtonTriggerLeft, nil case ButtonL3: return uinput.ButtonThumbLeft, nil case ButtonR1: return uinput.ButtonBumperRight, nil case ButtonR2: return uinput.ButtonTriggerRight, nil case ButtonR3: return uinput.ButtonThumbRight, nil case ButtonSelect: return uinput.ButtonSelect, nil case ButtonStart: return uinput.ButtonStart, nil case ButtonDpadUp: return uinput.ButtonDpadUp, nil case ButtonDpadDown: return uinput.ButtonDpadDown, nil case ButtonDpadLeft: return uinput.ButtonDpadLeft, nil case ButtonDpadRight: return uinput.ButtonDpadRight, nil default: return -1, fmt.Errorf("Invalid button name \"%s\"", bn) } } 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 \"%s\"", an) } }