housekeeping: Refactored API to separate packages

This commit is contained in:
2025-08-09 17:43:55 +02:00
parent ce0f466a0e
commit ae28a4d385
5 changed files with 47 additions and 43 deletions

View File

@@ -1,9 +1,11 @@
package main
package config
import (
"fmt"
"os"
"git.datalore.sh/datalore/midi-hid/translation"
"github.com/goccy/go-yaml"
"github.com/bendahl/uinput"
"github.com/charmbracelet/log"
@@ -84,8 +86,8 @@ func ParseConfig(path string) (Config, error) {
// 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) {
var controllerList ControllerList
func (config Config) Construct() (translation.ControllerList, error) {
var controllerList translation.ControllerList
for _, controllerConfig := range config.Controller {
actualController, err := controllerConfig.Construct()
@@ -102,8 +104,8 @@ func (config Config) Construct() (ControllerList, error) {
// 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) {
actualController, err := NewController(cc.PortName, cc.VendorID, cc.ProductID)
func (cc ControllerConfig) Construct() (*translation.Controller, error) {
actualController, err := translation.NewController(cc.PortName, cc.VendorID, cc.ProductID)
if err != nil {
return actualController, err
}
@@ -121,28 +123,28 @@ func (cc ControllerConfig) Construct() (*Controller, error) {
}
// Construct builds the Mapping object. Returns an error if config is invalid.
func (mc MappingConfig) Construct() (Mapping, error) {
func (mc MappingConfig) Construct() (translation.Mapping, error) {
switch mc.Type {
case ButtonMappingType:
button, err := mc.Button.Construct()
if err != nil {
return ButtonMapping{}, err
return translation.ButtonMapping{}, err
}
log.Debug("Parsed button mapping", "comment", mc.Comment, "midiChannel", mc.MidiChannel, "midiKey", mc.MidiKey, "button", button)
return ButtonMapping{mc.Comment, mc.MidiChannel, mc.MidiKey, button}, nil
return translation.ButtonMapping{mc.Comment, mc.MidiChannel, mc.MidiKey, button}, nil
case ControlMappingType:
axis, err := mc.Axis.Construct()
if err != nil {
return ControlMapping{}, err
return translation.ControlMapping{}, err
}
log.Debug("Parsed control mapping", "comment", mc.Comment, "midiChannel", mc.MidiChannel, "midiController", mc.MidiController, "axis", axis, "isSigned", mc.IsSigned, "deadzone", mc.Deadzone)
return ControlMapping{mc.Comment, mc.MidiChannel, mc.MidiController, axis, mc.IsSigned, mc.Deadzone}, nil
return translation.ControlMapping{mc.Comment, mc.MidiChannel, mc.MidiController, axis, mc.IsSigned, mc.Deadzone}, nil
default:
return ButtonMapping{}, fmt.Errorf("Invalid mapping type")
return translation.ButtonMapping{}, fmt.Errorf("Invalid mapping type")
}
}
@@ -189,16 +191,16 @@ 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() (translation.ControllerAxis, error) {
switch an {
case AxisLeftX:
return LeftX, nil
return translation.LeftX, nil
case AxisLeftY:
return LeftY, nil
return translation.LeftY, nil
case AxisRightX:
return RightX, nil
return translation.RightX, nil
case AxisRightY:
return RightY, nil
return translation.RightY, nil
default:
return -1, fmt.Errorf("Invalid axis name \"%s\"", an)
}

View File

@@ -5,6 +5,8 @@ import (
"os"
"os/signal"
"git.datalore.sh/datalore/midi-hid/config"
"github.com/charmbracelet/log"
"gitlab.com/gomidi/midi/v2"
)
@@ -34,8 +36,8 @@ func main() {
}
log.Info("Starting...")
config := must(ParseConfig(configPath))
controllerList := must(config.Construct())
conf := must(config.ParseConfig(configPath))
controllerList := must(conf.Construct())
defer controllerList.Stop()
// wait for SIGINT

View File

@@ -1,4 +1,4 @@
package main
package translation
import (
"github.com/charmbracelet/log"

View File

@@ -1,4 +1,4 @@
package main
package translation
import (
"fmt"
@@ -18,10 +18,10 @@ type Mapping interface {
// A ButtonMapping maps a MIDI Note to a gamepad button.
type ButtonMapping struct {
comment string
midiChannel uint8
midiKey uint8
gamepadKey int
CommentStr string
MidiChannel uint8
MidiKey uint8
GamepadKey int
}
// Is checks if the MIDI message msg triggers this Mapping, without actually triggering it.
@@ -30,7 +30,7 @@ func (m ButtonMapping) Is(msg midi.Message) bool {
switch {
case msg.GetNoteOn(&channel, &key, nil), msg.GetNoteOff(&channel, &key, nil):
return (m.midiChannel == channel && m.midiKey == key)
return (m.MidiChannel == channel && m.MidiKey == key)
default:
return false
}
@@ -45,13 +45,13 @@ func (m ButtonMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamep
switch msg.Type() {
case midi.NoteOnMsg:
if velocity != 0 {
log.Debug(m.comment, "status", "down")
return virtGamepad.ButtonDown(m.gamepadKey)
log.Debug(m.CommentStr, "status", "down")
return virtGamepad.ButtonDown(m.GamepadKey)
}
fallthrough // if reached here, velocity is 0 -> NoteOff
case midi.NoteOffMsg:
log.Debug(m.comment, "status", "up")
return virtGamepad.ButtonUp(m.gamepadKey)
log.Debug(m.CommentStr, "status", "up")
return virtGamepad.ButtonUp(m.GamepadKey)
default:
return fmt.Errorf("Invalid message type triggered ButtonMapping")
}
@@ -62,7 +62,7 @@ func (m ButtonMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Gamep
// Comment returns the Mappings comment.
func (m ButtonMapping) Comment() string {
return m.comment
return m.CommentStr
}
type ControllerAxis int
@@ -75,12 +75,12 @@ const (
)
type ControlMapping struct {
comment string
midiChannel uint8
midiController uint8
axis ControllerAxis
isSigned bool
deadzone float64
CommentStr string
MidiChannel uint8
MidiController uint8
Axis ControllerAxis
IsSigned bool
Deadzone float64
}
// Is checks if the MIDI message msg triggers this Mapping, without actually triggering it.
@@ -88,7 +88,7 @@ func (m ControlMapping) Is(msg midi.Message) bool {
var channel, controller uint8
if msg.GetControlChange(&channel, &controller, nil) {
return (m.midiChannel == channel && m.midiController == controller)
return (m.MidiChannel == channel && m.MidiController == controller)
} else {
return false
}
@@ -107,18 +107,18 @@ func (m ControlMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Game
// value is 0-127, normalise
valueNormalised = float64(valueAbsolute) / 127
if m.isSigned {
if m.IsSigned {
valueNormalised *= 2
valueNormalised -= 1
}
if math.Abs(valueNormalised) < m.deadzone {
if math.Abs(valueNormalised) < m.Deadzone {
valueNormalised = 0
}
log.Debug(m.comment, "value", valueNormalised, "deadzone", m.deadzone)
log.Debug(m.CommentStr, "value", valueNormalised, "deadzone", m.Deadzone)
switch m.axis {
switch m.Axis {
case LeftX:
return virtGamepad.LeftStickMoveX(float32(valueNormalised))
case LeftY:
@@ -135,5 +135,5 @@ func (m ControlMapping) TriggerIfMatch(msg midi.Message, virtGamepad uinput.Game
// Comment returns the Mappings comment.
func (m ControlMapping) Comment() string {
return m.comment
return m.CommentStr
}

View File

@@ -1,4 +1,4 @@
package main
package translation
import (
"gitlab.com/gomidi/midi/v2"