diff --git a/docs/examples/ruletypes.yml b/docs/examples/ruletypes.yml index 8bc0fe8..fe54b15 100644 --- a/docs/examples/ruletypes.yml +++ b/docs/examples/ruletypes.yml @@ -70,17 +70,6 @@ rules: device: main axis: RZ - # Hat mapping. Hats are technically an axis, but only output -1, 0, or 1, so we don't normalize - # them to an output range, we just pass them through mostly unmodified - - type: hat - input: - device: flightstick - inverted: true # hats do support inversion. As with other rule types, this only has an effect on *inputs*. - hat: hat0x # a typical joystick hat actually has 2 hat axes: x and y - output: - device: main - hat: hat0x - # Straightforward button mapping - type: button input: @@ -122,9 +111,8 @@ rules: input: device: flightstick axis: ABS_RY # This axis commonly represents thumbsticks - deadzones: - - start: 0 - end: 30000 + deadzone_start: 0 + deadzone_end: 30000 output: device: main button: BTN_BASE4 @@ -141,9 +129,8 @@ rules: input: device: flightstick axis: ABS_Z - deadzones: - - start: 0 - end: 500 + deadzone_start: 0 + deadzone_end: 500 output: device: mouse button: REL_WHEEL \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md index 7ac1945..5544f1b 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -48,7 +48,6 @@ All `rules` must have a `type` parameter. Valid values for this parameter are: * `axis-combined` - a mapping that combines 2 input axes into a single output axis. * `axis-to-button` - causes an axis input to produce a button output. This can be repeated with variable speed proportional to the axis' input value * `axis-to-relaxis` - like axis-to-button, but produces a "relative axis" output value. This is useful for simulating mouse scrollwheel and movement events. -* `hat` - a special type of axis with ternary output. Each joystick hat will typically be 2 hat axes named `ABS_HAT0X` / `ABS_HAT0Y`, where the `0` is an index between 0 - 3. So for a typical hat you would define 2 `hat` rules. Configuration options for each rule type vary. See [examples/ruletypes.yml](examples/ruletypes.yml) for an example of each type with all options specified. diff --git a/internal/configparser/ruleconfig.go b/internal/configparser/ruleconfig.go index 53c3c35..b41e339 100644 --- a/internal/configparser/ruleconfig.go +++ b/internal/configparser/ruleconfig.go @@ -54,10 +54,6 @@ func (dc *RuleConfig) UnmarshalYAML(unmarshal func(data interface{}) error) erro config := RuleConfigModeSelect{} err = unmarshal(&config) dc.Config = config - case RuleTypeHat: - config := RuleConfigHat{} - err = unmarshal(&config) - dc.Config = config } return err diff --git a/internal/configparser/ruletarget.go b/internal/configparser/ruletarget.go index 2a2a12a..094ea7b 100644 --- a/internal/configparser/ruletarget.go +++ b/internal/configparser/ruletarget.go @@ -31,9 +31,3 @@ type RuleTargetConfigRelaxis struct { type RuleTargetConfigModeSelect struct { Modes []string } - -type RuleTargetConfigHat struct { - Device string - Hat string - Inverted bool -} diff --git a/internal/configparser/ruletype.go b/internal/configparser/ruletype.go index d305570..7f43001 100644 --- a/internal/configparser/ruletype.go +++ b/internal/configparser/ruletype.go @@ -18,7 +18,6 @@ const ( RuleTypeAxisToButton RuleType = "axis-to-button" RuleTypeAxisToRelaxis RuleType = "axis-to-relaxis" RuleTypeModeSelect RuleType = "mode-select" - RuleTypeHat RuleType = "hat" ) var ( @@ -31,7 +30,6 @@ var ( "axis-to-button": RuleTypeAxisToButton, "axis-to-relaxis": RuleTypeAxisToRelaxis, "mode-select": RuleTypeModeSelect, - "hat": RuleTypeHat, } ) diff --git a/internal/configparser/schema.go b/internal/configparser/schema.go index 55ddb24..f7a0035 100644 --- a/internal/configparser/schema.go +++ b/internal/configparser/schema.go @@ -40,11 +40,6 @@ type RuleConfigAxis struct { Output RuleTargetConfigAxis } -type RuleConfigHat struct { - Input RuleTargetConfigHat - Output RuleTargetConfigHat -} - type RuleConfigAxisCombined struct { InputLower RuleTargetConfigAxis `yaml:"input_lower,omitempty"` InputUpper RuleTargetConfigAxis `yaml:"input_upper,omitempty"` diff --git a/internal/mappingrules/deadzone.go b/internal/mappingrules/deadzone.go index 23af465..c3e39b9 100644 --- a/internal/mappingrules/deadzone.go +++ b/internal/mappingrules/deadzone.go @@ -35,6 +35,7 @@ func NewDeadzoneFromConfig(dzConfig configparser.DeadzoneConfig, device Device, dz := Deadzone{} dz.Emit = dzConfig.Emit dz.EmitValue = dzConfig.Value + fmt.Printf("DEBUG: %d, %d\n", dzConfig.Value, dz.EmitValue) var min, max int32 absInfoMap, err := device.AbsInfos() diff --git a/internal/mappingrules/init_rules.go b/internal/mappingrules/init_rules.go index 28d4ea8..f621875 100644 --- a/internal/mappingrules/init_rules.go +++ b/internal/mappingrules/init_rules.go @@ -49,8 +49,6 @@ func NewRule(config configparser.RuleConfig, pDevs map[string]Device, vDevs map[ newRule, err = NewMappingRuleAxisToRelaxis(config.Config.(configparser.RuleConfigAxisToRelaxis), pDevs, vDevs, base) case configparser.RuleTypeModeSelect: newRule, err = NewMappingRuleModeSelect(config.Config.(configparser.RuleConfigModeSelect), pDevs, modes, base) - case configparser.RuleTypeHat: - newRule, err = NewMappingRuleHat(config.Config.(configparser.RuleConfigHat), pDevs, vDevs, base) default: // Shouldn't actually be possible to get here... err = fmt.Errorf("bad rule type '%s' for rule '%s'", config.Type, config.Name) diff --git a/internal/mappingrules/interfaces.go b/internal/mappingrules/interfaces.go index 96594c6..33b290a 100644 --- a/internal/mappingrules/interfaces.go +++ b/internal/mappingrules/interfaces.go @@ -22,6 +22,9 @@ type RuleTarget interface { // (e.g., inverting the value if Inverted == true) NormalizeValue(int32) int32 + // MatchEvent returns true if the provided device and input event are a match for this rule target + ValidateEvent(*evdev.InputDevice, *evdev.InputEvent) bool + // CreateEvent creates an event that can be emitted on a virtual device. // For RuleTargetModeSelect, this method modifies the active mode and returns nil. // @@ -32,7 +35,6 @@ type RuleTarget interface { // for most implementations. CreateEvent(int32, *string) *evdev.InputEvent - // MatchEvent returns true if the provided device and input event are a match for this rule target MatchEvent(device Device, event *evdev.InputEvent) bool } diff --git a/internal/mappingrules/mapping_rule_hat.go b/internal/mappingrules/mapping_rule_hat.go deleted file mode 100644 index ba04323..0000000 --- a/internal/mappingrules/mapping_rule_hat.go +++ /dev/null @@ -1,45 +0,0 @@ -package mappingrules - -import ( - "git.annabunches.net/annabunches/joyful/internal/configparser" - "github.com/holoplot/go-evdev" -) - -// A Simple Mapping Rule can map a button to a button or an axis to an axis. -type MappingRuleHat struct { - MappingRuleBase - Input *RuleTargetHat - Output *RuleTargetHat -} - -func NewMappingRuleHat(ruleConfig configparser.RuleConfigHat, - pDevs map[string]Device, - vDevs map[string]Device, - base MappingRuleBase) (*MappingRuleHat, error) { - - input, err := NewRuleTargetHatFromConfig(ruleConfig.Input, pDevs) - if err != nil { - return nil, err - } - - output, err := NewRuleTargetHatFromConfig(ruleConfig.Output, vDevs) - if err != nil { - return nil, err - } - - return &MappingRuleHat{ - MappingRuleBase: base, - Input: input, - Output: output, - }, nil -} - -func (rule *MappingRuleHat) MatchEvent(device Device, event *evdev.InputEvent, mode *string) (*evdev.InputDevice, *evdev.InputEvent) { - if !rule.MappingRuleBase.modeCheck(mode) || - !rule.Input.MatchEvent(device, event) { - return nil, nil - } - - // The cast here is safe because the interface is only ever different for unit tests - return rule.Output.Device.(*evdev.InputDevice), rule.Output.CreateEvent(rule.Input.NormalizeValue(event.Value), mode) -} diff --git a/internal/mappingrules/rule_target_axis.go b/internal/mappingrules/rule_target_axis.go index fcf1dcb..6fa62f6 100644 --- a/internal/mappingrules/rule_target_axis.go +++ b/internal/mappingrules/rule_target_axis.go @@ -117,6 +117,7 @@ func (target *RuleTargetAxis) NormalizeValue(value int32) int32 { } func (target *RuleTargetAxis) CreateEvent(value int32, mode *string) *evdev.InputEvent { + fmt.Println("DEBUG: Emitting event") value = Clamp(value, AxisValueMin, AxisValueMax) return &evdev.InputEvent{ Type: evdev.EV_ABS, diff --git a/internal/mappingrules/rule_target_hat.go b/internal/mappingrules/rule_target_hat.go deleted file mode 100644 index 464e559..0000000 --- a/internal/mappingrules/rule_target_hat.go +++ /dev/null @@ -1,53 +0,0 @@ -package mappingrules - -import ( - "fmt" - - "git.annabunches.net/annabunches/joyful/internal/configparser" - "git.annabunches.net/annabunches/joyful/internal/eventcodes" - "github.com/holoplot/go-evdev" -) - -type RuleTargetHat struct { - Device Device - Hat evdev.EvCode - Inverted bool -} - -func NewRuleTargetHatFromConfig(config configparser.RuleTargetConfigHat, devs map[string]Device) (*RuleTargetHat, error) { - dev, ok := devs[config.Device] - if !ok { - return nil, fmt.Errorf("device '%s' not found", config.Device) - } - - code, err := eventcodes.ParseCode(config.Hat, eventcodes.CodePrefixAxis) - if err != nil { - return nil, err - } - - return &RuleTargetHat{ - Device: dev, - Hat: code, - Inverted: config.Inverted, - }, nil -} - -func (target *RuleTargetHat) NormalizeValue(value int32) int32 { - if !target.Inverted { - return value - } - - return value * -1 -} - -func (target *RuleTargetHat) CreateEvent(value int32, _ *string) *evdev.InputEvent { - return &evdev.InputEvent{ - Type: evdev.EV_ABS, - Code: target.Hat, - Value: value, - } -} - -func (target *RuleTargetHat) MatchEvent(device Device, event *evdev.InputEvent) bool { - return device == target.Device && event.Code == target.Hat -} diff --git a/internal/virtualdevice/variables.go b/internal/virtualdevice/variables.go index 7102bd5..11adb46 100644 --- a/internal/virtualdevice/variables.go +++ b/internal/virtualdevice/variables.go @@ -49,15 +49,6 @@ var ( evdev.ABS_RZ, evdev.ABS_THROTTLE, // Also called "Slider" or "Slider1" evdev.ABS_RUDDER, // Also called "Dial", "Slider2", or "RSlider" - // Hats - evdev.ABS_HAT0X, - evdev.ABS_HAT0Y, - evdev.ABS_HAT1X, - evdev.ABS_HAT1Y, - evdev.ABS_HAT2X, - evdev.ABS_HAT2Y, - evdev.ABS_HAT3X, - evdev.ABS_HAT3Y, }, evdev.EV_KEY: { evdev.BTN_TRIGGER, diff --git a/readme.md b/readme.md index afa5c8f..f9c0e88 100644 --- a/readme.md +++ b/readme.md @@ -10,13 +10,13 @@ Joyful is ideal for Linux gamers who enjoy space and flight sims and miss the fe ### Current Features -* Create virtual devices with up to 8 axes, 4 hats, and 74 buttons. +* Create virtual devices with up to 8 axes and 74 buttons. * Flexible rule system that allows several different types of rules, including: - * Simple 1:1 mappings of buttons, axes, and hats: Button1 -> VirtualButtonA + * Simple 1:1 mappings of buttons and axes: Button1 -> VirtualButtonA * Combination mappings: Button1 + Button2 -> VirtualButtonA * "Split" axis mapping: map sections of an axis to different outputs using deadzones. * "Combined" axis mapping: map two physical axes to one virtual axis. - * Axis -> Button mapping with optional "proportional" repeat speed (i.e. repeat faster as the axis is engaged further) + * Axis -> button mapping with optional "proportional" repeat speed (i.e. repeat faster as the axis is engaged further) * Axis -> Relative Axis mapping, for converting a joystick axis to mouse movement and scrollwheel events. * Define keyboard, mouse, and gamepad outputs in addition to joysticks. * Configure per-rule configurable deadzones for axes, with multiple ways to specify deadzones. @@ -27,10 +27,10 @@ Joyful is ideal for Linux gamers who enjoy space and flight sims and miss the fe * Macros - have a single input produce a sequence of button presses with configurable pauses. * Sequence combos - Button1, Button2, Button3 -> VirtualButtonA -* Hat -> Button and Button -> Hat support. -* HIDRAW support for more button options +* Hat support +* HIDRAW support for more button options. * Sensitivity Curves? -* Packaged builds for non-Arch distributions. +* Packaged builds non-Arch distributions. ## Configure