Move initialization code closer to the appropriate structs. #17
17 changed files with 198 additions and 194 deletions
|
@ -1,156 +0,0 @@
|
|||
package mappingrules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
"git.annabunches.net/annabunches/joyful/internal/eventcodes"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
func makeRuleTargetButton(targetConfig configparser.RuleTargetConfigButton, devs map[string]Device) (*RuleTargetButton, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCodeButton(targetConfig.Button)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetButton(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
targetConfig.Inverted,
|
||||
)
|
||||
}
|
||||
|
||||
func makeRuleTargetAxis(targetConfig configparser.RuleTargetConfigAxis, devs map[string]Device) (*RuleTargetAxis, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
if targetConfig.DeadzoneEnd < targetConfig.DeadzoneStart {
|
||||
return nil, errors.New("deadzone_end must be greater than deadzone_start")
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCode(targetConfig.Axis, eventcodes.CodePrefixAxis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deadzoneStart, deadzoneEnd, err := calculateDeadzones(targetConfig, device, eventCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetAxis(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
targetConfig.Inverted,
|
||||
deadzoneStart,
|
||||
deadzoneEnd,
|
||||
)
|
||||
}
|
||||
|
||||
func makeRuleTargetRelaxis(targetConfig configparser.RuleTargetConfigRelaxis, devs map[string]Device) (*RuleTargetRelaxis, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCode(targetConfig.Axis, eventcodes.CodePrefixRelaxis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetRelaxis(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
)
|
||||
}
|
||||
|
||||
func makeRuleTargetModeSelect(targetConfig configparser.RuleTargetConfigModeSelect, allModes []string) (*RuleTargetModeSelect, error) {
|
||||
if ok := validateModes(targetConfig.Modes, allModes); !ok {
|
||||
return nil, errors.New("undefined mode in mode select list")
|
||||
}
|
||||
|
||||
return NewRuleTargetModeSelect(targetConfig.Modes)
|
||||
}
|
||||
|
||||
// calculateDeadzones produces the deadzone start and end values in absolute terms
|
||||
func calculateDeadzones(targetConfig configparser.RuleTargetConfigAxis, device Device, axis evdev.EvCode) (int32, int32, error) {
|
||||
|
||||
var deadzoneStart, deadzoneEnd int32
|
||||
deadzoneStart = 0
|
||||
deadzoneEnd = 0
|
||||
|
||||
if targetConfig.DeadzoneStart != 0 || targetConfig.DeadzoneEnd != 0 {
|
||||
return targetConfig.DeadzoneStart, targetConfig.DeadzoneEnd, nil
|
||||
}
|
||||
|
||||
var min, max int32
|
||||
absInfoMap, err := device.AbsInfos()
|
||||
|
||||
if err != nil {
|
||||
min = AxisValueMin
|
||||
max = AxisValueMax
|
||||
} else {
|
||||
absInfo := absInfoMap[axis]
|
||||
min = absInfo.Minimum
|
||||
max = absInfo.Maximum
|
||||
}
|
||||
|
||||
if targetConfig.DeadzoneCenter < min || targetConfig.DeadzoneCenter > max {
|
||||
return 0, 0, fmt.Errorf("deadzone_center '%d' is out of bounds", targetConfig.DeadzoneCenter)
|
||||
}
|
||||
|
||||
switch {
|
||||
case targetConfig.DeadzoneSize != 0:
|
||||
deadzoneStart = targetConfig.DeadzoneCenter - targetConfig.DeadzoneSize/2
|
||||
deadzoneEnd = targetConfig.DeadzoneCenter + targetConfig.DeadzoneSize/2
|
||||
case targetConfig.DeadzoneSizePercent != 0:
|
||||
deadzoneSize := (max - min) / targetConfig.DeadzoneSizePercent
|
||||
deadzoneStart = targetConfig.DeadzoneCenter - deadzoneSize/2
|
||||
deadzoneEnd = targetConfig.DeadzoneCenter + deadzoneSize/2
|
||||
}
|
||||
|
||||
deadzoneStart, deadzoneEnd = clampAndShift(deadzoneStart, deadzoneEnd, min, max)
|
||||
return deadzoneStart, deadzoneEnd, nil
|
||||
}
|
||||
|
||||
func clampAndShift(start, end, min, max int32) (int32, int32) {
|
||||
if start < min {
|
||||
end += min - start
|
||||
start = min
|
||||
}
|
||||
if end > max {
|
||||
start -= end - max
|
||||
end = max
|
||||
}
|
||||
|
||||
return start, end
|
||||
}
|
||||
|
||||
// validateModes checks the provided modes against a larger subset of modes (usually all defined ones)
|
||||
// and returns false if any of the modes are not defined.
|
||||
func validateModes(modes []string, allModes []string) bool {
|
||||
if len(modes) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, mode := range modes {
|
||||
if !slices.Contains(allModes, mode) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
|
@ -53,41 +53,41 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetButton() {
|
|||
|
||||
t.Run("Standard keycode", func() {
|
||||
config.Button = "BTN_TRIGGER"
|
||||
rule, err := makeRuleTargetButton(config, t.devs)
|
||||
rule, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.BTN_TRIGGER, rule.Button)
|
||||
})
|
||||
|
||||
t.Run("Hex code", func() {
|
||||
config.Button = "0x2fd"
|
||||
rule, err := makeRuleTargetButton(config, t.devs)
|
||||
rule, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.EvCode(0x2fd), rule.Button)
|
||||
})
|
||||
|
||||
t.Run("Index", func() {
|
||||
config.Button = "3"
|
||||
rule, err := makeRuleTargetButton(config, t.devs)
|
||||
rule, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.BTN_TOP, rule.Button)
|
||||
})
|
||||
|
||||
t.Run("Index too high", func() {
|
||||
config.Button = "74"
|
||||
_, err := makeRuleTargetButton(config, t.devs)
|
||||
_, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
|
||||
t.Run("Un-prefixed keycode", func() {
|
||||
config.Button = "pinkie"
|
||||
rule, err := makeRuleTargetButton(config, t.devs)
|
||||
rule, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.BTN_PINKIE, rule.Button)
|
||||
})
|
||||
|
||||
t.Run("Invalid keycode", func() {
|
||||
config.Button = "foo"
|
||||
_, err := makeRuleTargetButton(config, t.devs)
|
||||
_, err := NewRuleTargetButtonFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
t.Run(fmt.Sprintf("KeyCode %s", tc.input), func() {
|
||||
config := configparser.RuleTargetConfigAxis{Device: "test"}
|
||||
config.Axis = tc.input
|
||||
rule, err := makeRuleTargetAxis(config, t.devs)
|
||||
rule, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(tc.output, rule.Axis)
|
||||
|
||||
|
@ -116,7 +116,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
t.Run("Invalid code", func() {
|
||||
config := configparser.RuleTargetConfigAxis{Device: "test"}
|
||||
config.Axis = "foo"
|
||||
_, err := makeRuleTargetAxis(config, t.devs)
|
||||
_, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
|
||||
|
@ -125,7 +125,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
config.Axis = "x"
|
||||
config.DeadzoneEnd = 100
|
||||
config.DeadzoneStart = 1000
|
||||
_, err := makeRuleTargetAxis(config, t.devs)
|
||||
_, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
|
||||
|
@ -148,7 +148,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
DeadzoneCenter: tc.inCenter,
|
||||
DeadzoneSize: tc.inSize,
|
||||
}
|
||||
rule, err := makeRuleTargetAxis(config, t.devs)
|
||||
rule, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
|
||||
t.Nil(err)
|
||||
t.Equal(tc.outStart, rule.DeadzoneStart)
|
||||
|
@ -163,7 +163,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
DeadzoneCenter: 20000,
|
||||
DeadzoneSize: 500,
|
||||
}
|
||||
_, err := makeRuleTargetAxis(config, t.devs)
|
||||
_, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
|
||||
|
@ -186,7 +186,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
DeadzoneCenter: tc.inCenter,
|
||||
DeadzoneSizePercent: tc.inSizePercent,
|
||||
}
|
||||
rule, err := makeRuleTargetAxis(config, t.devs)
|
||||
rule, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
|
||||
t.Nil(err)
|
||||
t.Equal(tc.outStart, rule.DeadzoneStart)
|
||||
|
@ -201,7 +201,7 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetAxis() {
|
|||
DeadzoneCenter: 20000,
|
||||
DeadzoneSizePercent: 10,
|
||||
}
|
||||
_, err := makeRuleTargetAxis(config, t.devs)
|
||||
_, err := NewRuleTargetAxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
}
|
||||
|
@ -211,34 +211,34 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetRelaxis() {
|
|||
|
||||
t.Run("Standard keycode", func() {
|
||||
config.Axis = "REL_WHEEL"
|
||||
rule, err := makeRuleTargetRelaxis(config, t.devs)
|
||||
rule, err := NewRuleTargetRelaxisFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.REL_WHEEL, rule.Axis)
|
||||
})
|
||||
|
||||
t.Run("Hex keycode", func() {
|
||||
config.Axis = "0x00"
|
||||
rule, err := makeRuleTargetRelaxis(config, t.devs)
|
||||
rule, err := NewRuleTargetRelaxisFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.REL_X, rule.Axis)
|
||||
})
|
||||
|
||||
t.Run("Un-prefixed keycode", func() {
|
||||
config.Axis = "wheel"
|
||||
rule, err := makeRuleTargetRelaxis(config, t.devs)
|
||||
rule, err := NewRuleTargetRelaxisFromConfig(config, t.devs)
|
||||
t.Nil(err)
|
||||
t.EqualValues(evdev.REL_WHEEL, rule.Axis)
|
||||
})
|
||||
|
||||
t.Run("Invalid keycode", func() {
|
||||
config.Axis = "foo"
|
||||
_, err := makeRuleTargetRelaxis(config, t.devs)
|
||||
_, err := NewRuleTargetRelaxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
|
||||
t.Run("Incorrect axis type", func() {
|
||||
config.Axis = "ABS_X"
|
||||
_, err := makeRuleTargetRelaxis(config, t.devs)
|
||||
_, err := NewRuleTargetRelaxisFromConfig(config, t.devs)
|
||||
t.NotNil(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package mappingrules
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
|
@ -60,3 +61,19 @@ func NewRule(config configparser.RuleConfig, pDevs map[string]Device, vDevs map[
|
|||
|
||||
return newRule, nil
|
||||
}
|
||||
|
||||
// validateModes checks the provided modes against a larger subset of modes (usually all defined ones)
|
||||
// and returns false if any of the modes are not defined.
|
||||
func validateModes(modes []string, allModes []string) bool {
|
||||
if len(modes) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, mode := range modes {
|
||||
if !slices.Contains(allModes, mode) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ func NewMappingRuleAxis(ruleConfig configparser.RuleConfigAxis,
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleAxis, error) {
|
||||
|
||||
input, err := makeRuleTargetAxis(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetAxisFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetAxis(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetAxisFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@ func NewMappingRuleAxisCombined(ruleConfig configparser.RuleConfigAxisCombined,
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleAxisCombined, error) {
|
||||
|
||||
inputLower, err := makeRuleTargetAxis(ruleConfig.InputLower, pDevs)
|
||||
inputLower, err := NewRuleTargetAxisFromConfig(ruleConfig.InputLower, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inputUpper, err := makeRuleTargetAxis(ruleConfig.InputUpper, pDevs)
|
||||
inputUpper, err := NewRuleTargetAxisFromConfig(ruleConfig.InputUpper, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetAxis(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetAxisFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ func (t *MappingRuleAxisCombinedTests) TearDownSubTest() {
|
|||
t.inputDevice.Reset()
|
||||
}
|
||||
|
||||
// TODO: this test sucks
|
||||
func (t *MappingRuleAxisCombinedTests) TestNewMappingRuleAxisCombined() {
|
||||
t.inputDevice.Stub("AbsInfos").Return(map[evdev.EvCode]evdev.AbsInfo{
|
||||
evdev.ABS_X: {Minimum: 0, Maximum: 10000},
|
||||
|
|
|
@ -29,12 +29,12 @@ func NewMappingRuleAxisToButton(ruleConfig configparser.RuleConfigAxisToButton,
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleAxisToButton, error) {
|
||||
|
||||
input, err := makeRuleTargetAxis(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetAxisFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetButton(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetButtonFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ func NewMappingRuleAxisToRelaxis(ruleConfig configparser.RuleConfigAxisToRelaxis
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleAxisToRelaxis, error) {
|
||||
|
||||
input, err := makeRuleTargetAxis(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetAxisFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetRelaxis(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetRelaxisFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ func NewMappingRuleButton(ruleConfig configparser.RuleConfigButton,
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleButton, error) {
|
||||
|
||||
input, err := makeRuleTargetButton(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetButtonFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetButton(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetButtonFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ func NewMappingRuleButtonCombo(ruleConfig configparser.RuleConfigButtonCombo,
|
|||
|
||||
inputs := make([]*RuleTargetButton, 0)
|
||||
for _, inputConfig := range ruleConfig.Inputs {
|
||||
input, err := makeRuleTargetButton(inputConfig, pDevs)
|
||||
input, err := NewRuleTargetButtonFromConfig(inputConfig, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputs = append(inputs, input)
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetButton(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetButtonFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ func NewMappingRuleButtonLatched(ruleConfig configparser.RuleConfigButtonLatched
|
|||
vDevs map[string]Device,
|
||||
base MappingRuleBase) (*MappingRuleButtonLatched, error) {
|
||||
|
||||
input, err := makeRuleTargetButton(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetButtonFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetButton(ruleConfig.Output, vDevs)
|
||||
output, err := NewRuleTargetButtonFromConfig(ruleConfig.Output, vDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@ func NewMappingRuleModeSelect(ruleConfig configparser.RuleConfigModeSelect,
|
|||
modes []string,
|
||||
base MappingRuleBase) (*MappingRuleModeSelect, error) {
|
||||
|
||||
input, err := makeRuleTargetButton(ruleConfig.Input, pDevs)
|
||||
input, err := NewRuleTargetButtonFromConfig(ruleConfig.Input, pDevs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := makeRuleTargetModeSelect(ruleConfig.Output, modes)
|
||||
output, err := NewRuleTargetModeSelectFromConfig(ruleConfig.Output, modes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -28,3 +28,16 @@ func Clamp[T Numeric](value, min, max T) T {
|
|||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func clampAndShift(start, end, min, max int32) (int32, int32) {
|
||||
if start < min {
|
||||
end += min - start
|
||||
start = min
|
||||
}
|
||||
if end > max {
|
||||
start -= end - max
|
||||
end = max
|
||||
}
|
||||
|
||||
return start, end
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
"git.annabunches.net/annabunches/joyful/internal/eventcodes"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
|
@ -20,6 +22,77 @@ type RuleTargetAxis struct {
|
|||
deadzoneSize int32
|
||||
}
|
||||
|
||||
func NewRuleTargetAxisFromConfig(targetConfig configparser.RuleTargetConfigAxis, devs map[string]Device) (*RuleTargetAxis, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
if targetConfig.DeadzoneEnd < targetConfig.DeadzoneStart {
|
||||
return nil, errors.New("deadzone_end must be greater than deadzone_start")
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCode(targetConfig.Axis, eventcodes.CodePrefixAxis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deadzoneStart, deadzoneEnd, err := calculateDeadzones(targetConfig, device, eventCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetAxis(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
targetConfig.Inverted,
|
||||
deadzoneStart,
|
||||
deadzoneEnd,
|
||||
)
|
||||
}
|
||||
|
||||
// calculateDeadzones produces the deadzone start and end values in absolute terms
|
||||
func calculateDeadzones(targetConfig configparser.RuleTargetConfigAxis, device Device, axis evdev.EvCode) (int32, int32, error) {
|
||||
|
||||
var deadzoneStart, deadzoneEnd int32
|
||||
deadzoneStart = 0
|
||||
deadzoneEnd = 0
|
||||
|
||||
if targetConfig.DeadzoneStart != 0 || targetConfig.DeadzoneEnd != 0 {
|
||||
return targetConfig.DeadzoneStart, targetConfig.DeadzoneEnd, nil
|
||||
}
|
||||
|
||||
var min, max int32
|
||||
absInfoMap, err := device.AbsInfos()
|
||||
|
||||
if err != nil {
|
||||
min = AxisValueMin
|
||||
max = AxisValueMax
|
||||
} else {
|
||||
absInfo := absInfoMap[axis]
|
||||
min = absInfo.Minimum
|
||||
max = absInfo.Maximum
|
||||
}
|
||||
|
||||
if targetConfig.DeadzoneCenter < min || targetConfig.DeadzoneCenter > max {
|
||||
return 0, 0, fmt.Errorf("deadzone_center '%d' is out of bounds", targetConfig.DeadzoneCenter)
|
||||
}
|
||||
|
||||
switch {
|
||||
case targetConfig.DeadzoneSize != 0:
|
||||
deadzoneStart = targetConfig.DeadzoneCenter - targetConfig.DeadzoneSize/2
|
||||
deadzoneEnd = targetConfig.DeadzoneCenter + targetConfig.DeadzoneSize/2
|
||||
case targetConfig.DeadzoneSizePercent != 0:
|
||||
deadzoneSize := (max - min) / targetConfig.DeadzoneSizePercent
|
||||
deadzoneStart = targetConfig.DeadzoneCenter - deadzoneSize/2
|
||||
deadzoneEnd = targetConfig.DeadzoneCenter + deadzoneSize/2
|
||||
}
|
||||
|
||||
deadzoneStart, deadzoneEnd = clampAndShift(deadzoneStart, deadzoneEnd, min, max)
|
||||
return deadzoneStart, deadzoneEnd, nil
|
||||
}
|
||||
|
||||
func NewRuleTargetAxis(device_name string,
|
||||
device Device,
|
||||
axis evdev.EvCode,
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
package mappingrules
|
||||
|
||||
import "github.com/holoplot/go-evdev"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
"git.annabunches.net/annabunches/joyful/internal/eventcodes"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
type RuleTargetButton struct {
|
||||
DeviceName string
|
||||
|
@ -9,6 +15,25 @@ type RuleTargetButton struct {
|
|||
Inverted bool
|
||||
}
|
||||
|
||||
func NewRuleTargetButtonFromConfig(targetConfig configparser.RuleTargetConfigButton, devs map[string]Device) (*RuleTargetButton, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCodeButton(targetConfig.Button)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetButton(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
targetConfig.Inverted,
|
||||
)
|
||||
}
|
||||
|
||||
func NewRuleTargetButton(device_name string, device Device, code evdev.EvCode, inverted bool) (*RuleTargetButton, error) {
|
||||
return &RuleTargetButton{
|
||||
DeviceName: device_name,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"slices"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
"git.annabunches.net/annabunches/joyful/internal/logger"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
@ -12,6 +13,14 @@ type RuleTargetModeSelect struct {
|
|||
Modes []string
|
||||
}
|
||||
|
||||
func NewRuleTargetModeSelectFromConfig(targetConfig configparser.RuleTargetConfigModeSelect, allModes []string) (*RuleTargetModeSelect, error) {
|
||||
if ok := validateModes(targetConfig.Modes, allModes); !ok {
|
||||
return nil, errors.New("undefined mode in mode select list")
|
||||
}
|
||||
|
||||
return NewRuleTargetModeSelect(targetConfig.Modes)
|
||||
}
|
||||
|
||||
func NewRuleTargetModeSelect(modes []string) (*RuleTargetModeSelect, error) {
|
||||
if len(modes) == 0 {
|
||||
return nil, errors.New("cannot create RuleTargetModeSelect: mode list is empty")
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package mappingrules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
||||
"git.annabunches.net/annabunches/joyful/internal/eventcodes"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
|
@ -10,12 +14,30 @@ type RuleTargetRelaxis struct {
|
|||
Axis evdev.EvCode
|
||||
}
|
||||
|
||||
func NewRuleTargetRelaxis(device_name string,
|
||||
func NewRuleTargetRelaxisFromConfig(targetConfig configparser.RuleTargetConfigRelaxis, devs map[string]Device) (*RuleTargetRelaxis, error) {
|
||||
device, ok := devs[targetConfig.Device]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
eventCode, err := eventcodes.ParseCode(targetConfig.Axis, eventcodes.CodePrefixRelaxis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewRuleTargetRelaxis(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
eventCode,
|
||||
)
|
||||
}
|
||||
|
||||
func NewRuleTargetRelaxis(deviceName string,
|
||||
device Device,
|
||||
axis evdev.EvCode) (*RuleTargetRelaxis, error) {
|
||||
|
||||
return &RuleTargetRelaxis{
|
||||
DeviceName: device_name,
|
||||
DeviceName: deviceName,
|
||||
Device: device,
|
||||
Axis: axis,
|
||||
}, nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue