feat(mapping): Added mapping type for rotary encoders

This commit is contained in:
2025-08-29 20:28:31 +02:00
parent 0be958c8d1
commit b1b6f36087
2 changed files with 63 additions and 0 deletions

View File

@@ -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 {

View File

@@ -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 (