diff --git a/internal/config/configparser.go b/internal/config/configparser.go index 1f518c2..ae464d8 100644 --- a/internal/config/configparser.go +++ b/internal/config/configparser.go @@ -8,7 +8,6 @@ import ( "strings" "git.annabunches.net/annabunches/joyful/internal/logger" - "git.annabunches.net/annabunches/joyful/internal/mappingrules" "github.com/goccy/go-yaml" "github.com/holoplot/go-evdev" ) @@ -132,29 +131,6 @@ func (parser *ConfigParser) ConnectPhysicalDevices() map[string]*evdev.InputDevi return deviceMap } -func (parser *ConfigParser) BuildRules(pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) []mappingrules.MappingRule { - rules := make([]mappingrules.MappingRule, 0) - - for _, ruleConfig := range parser.config.Rules { - var newRule mappingrules.MappingRule - var err error - switch strings.ToLower(ruleConfig.Type) { - case RuleTypeSimple: - newRule, err = makeSimpleRule(ruleConfig, pDevs, vDevs) - case RuleTypeCombo: - newRule, err = makeComboRule(ruleConfig, pDevs, vDevs) - } - - if err != nil { - logger.LogError(err, "") - continue - } - rules = append(rules, newRule) - } - - return rules -} - func makeButtons(numButtons int) []evdev.EvCode { if numButtons > 56 { numButtons = 56 diff --git a/internal/config/rules.go b/internal/config/rules.go index cdacb75..3d7c478 100644 --- a/internal/config/rules.go +++ b/internal/config/rules.go @@ -2,12 +2,39 @@ package config import ( "fmt" + "strings" + "git.annabunches.net/annabunches/joyful/internal/logger" "git.annabunches.net/annabunches/joyful/internal/mappingrules" "github.com/holoplot/go-evdev" ) -func makeSimpleRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) (mappingrules.MappingRule, error) { +func (parser *ConfigParser) BuildRules(pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) []mappingrules.MappingRule { + rules := make([]mappingrules.MappingRule, 0) + + for _, ruleConfig := range parser.config.Rules { + var newRule mappingrules.MappingRule + var err error + switch strings.ToLower(ruleConfig.Type) { + case RuleTypeSimple: + newRule, err = makeSimpleRule(ruleConfig, pDevs, vDevs) + case RuleTypeCombo: + newRule, err = makeComboRule(ruleConfig, pDevs, vDevs) + case RuleTypeLatched: + newRule, err = makeLatchedRule(ruleConfig, pDevs, vDevs) + } + + if err != nil { + logger.LogError(err, "") + continue + } + rules = append(rules, newRule) + } + + return rules +} + +func makeSimpleRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) (*mappingrules.SimpleMappingRule, error) { input, err := makeRuleTarget(ruleConfig.Input, pDevs) if err != nil { return nil, err @@ -19,13 +46,15 @@ func makeSimpleRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, } return &mappingrules.SimpleMappingRule{ + MappingRuleBase: mappingrules.MappingRuleBase{ + Output: output, + }, Input: input, - Output: output, Name: ruleConfig.Name, }, nil } -func makeComboRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) (mappingrules.MappingRule, error) { +func makeComboRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) (*mappingrules.ComboMappingRule, error) { inputs := make([]mappingrules.RuleTarget, 0) for _, inputConfig := range ruleConfig.Inputs { input, err := makeRuleTarget(inputConfig, pDevs) @@ -41,12 +70,36 @@ func makeComboRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, v } return &mappingrules.ComboMappingRule{ + MappingRuleBase: mappingrules.MappingRuleBase{ + Output: output, + }, Inputs: inputs, - Output: output, + State: 0, Name: ruleConfig.Name, }, nil } +func makeLatchedRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) (*mappingrules.LatchedMappingRule, error) { + input, err := makeRuleTarget(ruleConfig.Input, pDevs) + if err != nil { + return nil, err + } + + output, err := makeRuleTarget(ruleConfig.Output, vDevs) + if err != nil { + return nil, err + } + + return &mappingrules.LatchedMappingRule{ + MappingRuleBase: mappingrules.MappingRuleBase{ + Output: output, + }, + Input: input, + Name: ruleConfig.Name, + State: false, + }, nil +} + // makeInputRuleTarget takes an Input declaration from the YAML and returns a fully formed RuleTarget. func makeRuleTarget(targetConfig RuleTargetConfig, devs map[string]*evdev.InputDevice) (mappingrules.RuleTarget, error) { ruleTarget := mappingrules.RuleTarget{} diff --git a/internal/config/variables.go b/internal/config/variables.go index caf6691..15d4ca7 100644 --- a/internal/config/variables.go +++ b/internal/config/variables.go @@ -67,4 +67,5 @@ const ( RuleTypeSimple = "simple" RuleTypeCombo = "combo" + RuleTypeLatched = "latched" ) diff --git a/internal/mappingrules/matching.go b/internal/mappingrules/matching.go index 9c2e3e0..4b38348 100644 --- a/internal/mappingrules/matching.go +++ b/internal/mappingrules/matching.go @@ -5,6 +5,10 @@ import ( "github.com/holoplot/go-evdev" ) +func (rule *MappingRuleBase) OutputName() string { + return rule.Output.DeviceName +} + // eventFromTarget creates an outputtable event from a RuleTarget func eventFromTarget(output RuleTarget, value int32) *evdev.InputEvent { return &evdev.InputEvent{ @@ -79,10 +83,21 @@ func (rule *ComboMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev return nil } -func (rule *SimpleMappingRule) OutputName() string { - return rule.Output.DeviceName -} +func (rule *LatchedMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.InputEvent) *evdev.InputEvent { + if device != rule.Input.Device || + event.Code != rule.Input.Code || + valueFromTarget(rule.Input, event) == 0 { + return nil + } -func (rule *ComboMappingRule) OutputName() string { - return rule.Output.DeviceName + // Input is pressed, so toggle state and emit event + var value int32 + rule.State = !rule.State + if rule.State { + value = 1 + } else { + value = 0 + } + + return eventFromTarget(rule.Output, value) } diff --git a/internal/mappingrules/types.go b/internal/mappingrules/types.go index 88d2a9d..ff39ef7 100644 --- a/internal/mappingrules/types.go +++ b/internal/mappingrules/types.go @@ -7,21 +7,32 @@ type MappingRule interface { OutputName() string } +type MappingRuleBase struct { + Output RuleTarget +} + // A Simple Mapping Rule can map a button to a button or an axis to an axis. type SimpleMappingRule struct { + MappingRuleBase Input RuleTarget - Output RuleTarget Name string } // A Combo Mapping Rule can require multiple physical button presses for a single output button type ComboMappingRule struct { + MappingRuleBase Inputs []RuleTarget - Output RuleTarget Name string State int } +type LatchedMappingRule struct { + MappingRuleBase + Input RuleTarget + Name string + State bool +} + type RuleTarget struct { DeviceName string Device *evdev.InputDevice