docs: Added godoc comments
This commit is contained in:
15
config.go
15
config.go
@@ -9,10 +9,12 @@ import (
|
|||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Config is the root type of a config, consisting of an arbitrary number of controller configs.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Controller []ControllerConfig `yaml:"controller"`
|
Controller []ControllerConfig `yaml:"controller"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ControllerConfig represents the data needed to later construct a Controller object.
|
||||||
type ControllerConfig struct {
|
type ControllerConfig struct {
|
||||||
PortName string `yaml:"portName"`
|
PortName string `yaml:"portName"`
|
||||||
VendorID uint16 `yaml:"vendorID"`
|
VendorID uint16 `yaml:"vendorID"`
|
||||||
@@ -20,6 +22,7 @@ type ControllerConfig struct {
|
|||||||
Mappings []MappingConfig `yaml:"mappings"`
|
Mappings []MappingConfig `yaml:"mappings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A MappingConfig consists of all data possibly needed to construct a mapping, both button and control.
|
||||||
type MappingConfig struct {
|
type MappingConfig struct {
|
||||||
Comment string `yaml:"comment"`
|
Comment string `yaml:"comment"`
|
||||||
Type MappingType `yaml:"type"`
|
Type MappingType `yaml:"type"`
|
||||||
@@ -61,6 +64,8 @@ const (
|
|||||||
AxisRightY AxisName = "right-y"
|
AxisRightY AxisName = "right-y"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ParseConfig takes the path to a config file and returns the parsed Config object,
|
||||||
|
// or an error if thrown.
|
||||||
func ParseConfig(path string) (Config, error) {
|
func ParseConfig(path string) (Config, error) {
|
||||||
var config Config
|
var config Config
|
||||||
|
|
||||||
@@ -77,6 +82,8 @@ func ParseConfig(path string) (Config, error) {
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct iterates over all ControllerConfigs and constructs the Controller objects.
|
||||||
|
// In case of a failure, it aborts and returns an error.
|
||||||
func (config Config) Construct() (ControllerList, error) {
|
func (config Config) Construct() (ControllerList, error) {
|
||||||
var controllerList ControllerList
|
var controllerList ControllerList
|
||||||
|
|
||||||
@@ -92,6 +99,9 @@ func (config Config) Construct() (ControllerList, error) {
|
|||||||
return controllerList, nil
|
return controllerList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct builds a Controller object and its corresponding mappings.
|
||||||
|
// Aborts and returns an error if the midi port was not found or one of
|
||||||
|
// the Mappings is invalid.
|
||||||
func (cc ControllerConfig) Construct() (*Controller, error) {
|
func (cc ControllerConfig) Construct() (*Controller, error) {
|
||||||
actualController, err := NewController(cc.PortName, cc.VendorID, cc.ProductID)
|
actualController, err := NewController(cc.PortName, cc.VendorID, cc.ProductID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -110,6 +120,7 @@ func (cc ControllerConfig) Construct() (*Controller, error) {
|
|||||||
return actualController, nil
|
return actualController, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct builds the Mapping object. Returns an error if config is invalid.
|
||||||
func (mc MappingConfig) Construct() (Mapping, error) {
|
func (mc MappingConfig) Construct() (Mapping, error) {
|
||||||
switch mc.Type {
|
switch mc.Type {
|
||||||
case ButtonMappingType:
|
case ButtonMappingType:
|
||||||
@@ -135,6 +146,8 @@ func (mc MappingConfig) Construct() (Mapping, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct converts a ButtonName to its corresponding key code, or returns an error if the
|
||||||
|
// name is unknown.
|
||||||
func (bn ButtonName) Construct() (int, error) {
|
func (bn ButtonName) Construct() (int, error) {
|
||||||
switch bn {
|
switch bn {
|
||||||
case ButtonNorth:
|
case ButtonNorth:
|
||||||
@@ -174,6 +187,8 @@ func (bn ButtonName) Construct() (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct converts an AxisName into the internal representation for a ControllerAxis.
|
||||||
|
// Returns an error if AxisName is invalid.
|
||||||
func (an AxisName) Construct() (ControllerAxis, error) {
|
func (an AxisName) Construct() (ControllerAxis, error) {
|
||||||
switch an {
|
switch an {
|
||||||
case AxisLeftX:
|
case AxisLeftX:
|
||||||
|
@@ -6,14 +6,18 @@ import (
|
|||||||
"github.com/bendahl/uinput"
|
"github.com/bendahl/uinput"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A ControllerList is a list of controllers. Duh.
|
||||||
type ControllerList []*Controller
|
type ControllerList []*Controller
|
||||||
|
|
||||||
|
// Stop iterates over all Controller objects and Stops their update loops and MIDI connections.
|
||||||
|
// Always call this for a clean shutdown. Meant to be deferred.
|
||||||
func (cl ControllerList) Stop() {
|
func (cl ControllerList) Stop() {
|
||||||
for _, controller := range cl {
|
for _, controller := range cl {
|
||||||
controller.Stop()
|
controller.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Controller object manages the translation from MIDI to uinput.
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
midiInput *MidiInput
|
midiInput *MidiInput
|
||||||
mappings []Mapping
|
mappings []Mapping
|
||||||
@@ -21,6 +25,8 @@ type Controller struct {
|
|||||||
virtGamepad uinput.Gamepad
|
virtGamepad uinput.Gamepad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewController builds a new Controller object reading from the MIDI port specified by portName,
|
||||||
|
// and registers a virtual uinput-Gamepad using vendorID and productID.
|
||||||
func NewController(portName string, vendorID, productID uint16) (*Controller, error) {
|
func NewController(portName string, vendorID, productID uint16) (*Controller, error) {
|
||||||
if vendorID == 0 && productID == 0 {
|
if vendorID == 0 && productID == 0 {
|
||||||
// if no IDs were defined, imitate XBox 360 controller
|
// if no IDs were defined, imitate XBox 360 controller
|
||||||
@@ -55,10 +61,12 @@ func NewController(portName string, vendorID, productID uint16) (*Controller, er
|
|||||||
return controller, nil
|
return controller, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMapping adds a mapping to the Controller.
|
||||||
func (c *Controller) AddMapping(mapping Mapping) {
|
func (c *Controller) AddMapping(mapping Mapping) {
|
||||||
c.mappings = append(c.mappings, mapping)
|
c.mappings = append(c.mappings, mapping)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop quits the update loop and terminates all corresponding connections.
|
||||||
func (c Controller) Stop() {
|
func (c Controller) Stop() {
|
||||||
c.midiInput.Stop()
|
c.midiInput.Stop()
|
||||||
c.abortChan <- struct{}{}
|
c.abortChan <- struct{}{}
|
||||||
|
10
mapping.go
10
mapping.go
@@ -9,12 +9,14 @@ import (
|
|||||||
"github.com/bendahl/uinput"
|
"github.com/bendahl/uinput"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A Mapping is an interface for all types of Mappings.
|
||||||
type Mapping interface {
|
type Mapping interface {
|
||||||
Is(midi.Message) bool
|
Is(midi.Message) bool
|
||||||
TriggerIfMatch(midi.Message, uinput.Gamepad) error
|
TriggerIfMatch(midi.Message, uinput.Gamepad) error
|
||||||
Comment() string
|
Comment() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ButtonMapping maps a MIDI Note to a gamepad button.
|
||||||
type ButtonMapping struct {
|
type ButtonMapping struct {
|
||||||
comment string
|
comment string
|
||||||
midiChannel uint8
|
midiChannel uint8
|
||||||
@@ -22,6 +24,7 @@ type ButtonMapping struct {
|
|||||||
gamepadKey int
|
gamepadKey int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is checks if the MIDI message msg triggers this Mapping, without actually triggering it.
|
||||||
func (m ButtonMapping) Is(msg midi.Message) bool {
|
func (m ButtonMapping) Is(msg midi.Message) bool {
|
||||||
var channel, key uint8
|
var channel, key uint8
|
||||||
|
|
||||||
@@ -33,6 +36,8 @@ func (m ButtonMapping) Is(msg midi.Message) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TriggerIfMatch checks if the MIDI message msg triggers this Mapping, and if so,
|
||||||
|
// sends the corresponding input to virtGamepad.
|
||||||
func (m ButtonMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamepad) error {
|
func (m ButtonMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamepad) error {
|
||||||
if m.Is(msg) {
|
if m.Is(msg) {
|
||||||
var velocity uint8
|
var velocity uint8
|
||||||
@@ -55,6 +60,7 @@ func (m ButtonMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamep
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comment returns the Mappings comment.
|
||||||
func (m ButtonMapping) Comment() string {
|
func (m ButtonMapping) Comment() string {
|
||||||
return m.comment
|
return m.comment
|
||||||
}
|
}
|
||||||
@@ -77,6 +83,7 @@ type ControlMapping struct {
|
|||||||
deadzone float64
|
deadzone float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is checks if the MIDI message msg triggers this Mapping, without actually triggering it.
|
||||||
func (m ControlMapping) Is(msg midi.Message) bool {
|
func (m ControlMapping) Is(msg midi.Message) bool {
|
||||||
var channel, controller uint8
|
var channel, controller uint8
|
||||||
|
|
||||||
@@ -87,6 +94,8 @@ func (m ControlMapping) Is(msg midi.Message) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TriggerIfMatch checks if the MIDI message msg triggers this Mapping, and if so,
|
||||||
|
// sends the corresponding input to virtGamepad.
|
||||||
func (m ControlMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamepad) error {
|
func (m ControlMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamepad) error {
|
||||||
if m.Is(msg) {
|
if m.Is(msg) {
|
||||||
var (
|
var (
|
||||||
@@ -124,6 +133,7 @@ func (m ControlMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Game
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comment returns the Mappings comment.
|
||||||
func (m ControlMapping) Comment() string {
|
func (m ControlMapping) Comment() string {
|
||||||
return m.comment
|
return m.comment
|
||||||
}
|
}
|
||||||
|
4
midi.go
4
midi.go
@@ -6,12 +6,16 @@ import (
|
|||||||
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
|
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A MidiInput represents a MIDI input and provides a channel to read incoming
|
||||||
|
// Messages, as well as a Stop function to terminate the connection.
|
||||||
type MidiInput struct {
|
type MidiInput struct {
|
||||||
input drivers.In
|
input drivers.In
|
||||||
Messages chan midi.Message
|
Messages chan midi.Message
|
||||||
Stop func()
|
Stop func()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMidiInput initialises a MidiInput object connected to the MIDI port specified
|
||||||
|
// by portName. Retuns an error if the connection fails.
|
||||||
func NewMidiInput(portName string) (*MidiInput, error) {
|
func NewMidiInput(portName string) (*MidiInput, error) {
|
||||||
input, err := midi.FindInPort(portName)
|
input, err := midi.FindInPort(portName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user