diff --git a/config/config.go b/config/config.go index fe1340a..b5c62d0 100644 --- a/config/config.go +++ b/config/config.go @@ -32,6 +32,7 @@ type MappingConfig struct { MidiKey uint8 `yaml:"midiKey"` MidiController uint8 `yaml:"midiController"` Button ButtonName `yaml:"button"` + ButtonNegative ButtonName `yaml:"buttonNegative"` Axis AxisName `yaml:"axis"` IsSigned bool `yaml:"isSigned"` Deadzone float64 `yaml:"deadzone"` @@ -44,6 +45,7 @@ type AxisName string const ( ButtonMappingType MappingType = "button" ControlMappingType MappingType = "control" + EncoderMappingType MappingType = "encoder" ButtonNorth ButtonName = "north" ButtonEast ButtonName = "east" ButtonSouth ButtonName = "south" @@ -134,6 +136,20 @@ func (mc MappingConfig) Construct() (translation.Mapping, error) { log.Debug("Parsed button mapping", "comment", mc.Comment, "midiChannel", mc.MidiChannel, "midiKey", mc.MidiKey, "button", button) return translation.ButtonMapping{mc.Comment, mc.MidiChannel, mc.MidiKey, button}, nil + case EncoderMappingType: + button, err := mc.Button.Construct() + if err != nil { + return translation.EncoderMapping{}, err + } + + buttonNegative, err := mc.ButtonNegative.Construct() + if err != nil { + return translation.EncoderMapping{}, err + } + + log.Debug("Parsed encoder mapping", "comment", mc.Comment, "midiChannel", mc.MidiChannel, "midiController", mc.MidiController, "button", button, "buttonNegative", buttonNegative) + + return translation.EncoderMapping{mc.Comment, mc.MidiChannel, mc.MidiController, button, buttonNegative}, nil case ControlMappingType: axis, err := mc.Axis.Construct() if err != nil { diff --git a/translation/mapping.go b/translation/mapping.go index 9867695..28cbd88 100644 --- a/translation/mapping.go +++ b/translation/mapping.go @@ -65,6 +65,53 @@ func (m ButtonMapping) Comment() string { return m.CommentStr } +// An EncoderMapping maps a MIDI Controller to two buttons. +type EncoderMapping struct { + CommentStr string + MidiChannel uint8 + MidiController uint8 + GamepadKeyPositive int + GamepadKeyNegative int +} + +// Is checks if the MIDI message msg triggers this Mapping, without actually triggering it. +func (m EncoderMapping) Is(msg midi.Message) bool { + var channel, controller uint8 + + if msg.GetControlChange(&channel, &controller, nil) { + return (m.MidiChannel == channel && m.MidiController == controller) + } else { + return false + } +} + +// TriggerIfMatch checks if the MIDI message msg triggers this Mapping, and if so, +// sends the corresponding input to virtGamepad. +func (m EncoderMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamepad) error { + if m.Is(msg) { + var valueAbsolute uint8 + + msg.GetControlChange(nil, nil, &valueAbsolute) + + switch valueAbsolute { + case 1: + log.Debug(m.CommentStr, "status", "increased") + return virtGamepad.ButtonPress(m.GamepadKeyPositive) + case 127: + log.Debug(m.CommentStr, "status", "decreased") + return virtGamepad.ButtonPress(m.GamepadKeyNegative) + default: + return fmt.Errorf("Invalid message type triggered ButtonMapping") + } + } + + return nil +} + +// Comment returns the Mappings comment. +func (m EncoderMapping) Comment() string { + return m.CommentStr +} type ControllerAxis int const (