Implement basic config file parsing and create virtual devices from config file.
This commit is contained in:
parent
eeebb6d0b1
commit
faa51bdda2
6 changed files with 156 additions and 88 deletions
|
@ -1,6 +1,7 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -12,19 +13,23 @@ import (
|
|||
)
|
||||
|
||||
type ConfigParser struct {
|
||||
config Config
|
||||
configFiles []string
|
||||
config Config
|
||||
}
|
||||
|
||||
// Parse all the config files and store the config data for further use
|
||||
func (parser *ConfigParser) Parse(directory string) {
|
||||
func (parser *ConfigParser) Parse(directory string) error {
|
||||
parser.config = Config{}
|
||||
|
||||
// Find the config files in the directory
|
||||
dirEntries, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
err = os.Mkdir(directory, 0755)
|
||||
logger.FatalIfError(err, "Failed to create config directory at "+directory)
|
||||
if err != nil {
|
||||
return errors.New("Failed to create config directory at " + directory)
|
||||
}
|
||||
}
|
||||
|
||||
// Open each yaml file and add its contents to the global config
|
||||
for _, file := range dirEntries {
|
||||
name := file.Name()
|
||||
if file.IsDir() || !(strings.HasSuffix(name, ".yaml") || strings.HasSuffix(name, ".yml")) {
|
||||
|
@ -33,42 +38,41 @@ func (parser *ConfigParser) Parse(directory string) {
|
|||
|
||||
filePath := filepath.Join(directory, name)
|
||||
if strings.HasSuffix(filePath, ".yaml") || strings.HasSuffix(filePath, ".yml") {
|
||||
parser.configFiles = append(parser.configFiles, filePath)
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
logger.LogError(err, "Error while opening config file")
|
||||
continue
|
||||
}
|
||||
newConfig := Config{}
|
||||
err = yaml.Unmarshal(data, &newConfig)
|
||||
logger.LogIfError(err, "Error parsing YAML")
|
||||
parser.config.Rules = append(parser.config.Rules, newConfig.Rules...)
|
||||
parser.config.Devices = append(parser.config.Devices, newConfig.Devices...)
|
||||
// parser.config.Groups = append(parser.config.Groups, newConfig.Groups...)
|
||||
}
|
||||
}
|
||||
|
||||
rawData := parser.parseConfigFiles()
|
||||
err = yaml.Unmarshal(rawData, &parser.config)
|
||||
logger.FatalIfError(err, "Failed to parse config")
|
||||
}
|
||||
|
||||
// Open each config file and concatenate their contents
|
||||
func (parser *ConfigParser) parseConfigFiles() []byte {
|
||||
var rawData []byte
|
||||
|
||||
for _, filePath := range parser.configFiles {
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
logger.LogIfError(err, fmt.Sprintf("Failed to read config file '%s'", filePath))
|
||||
continue
|
||||
}
|
||||
|
||||
rawData = append(rawData, data...)
|
||||
rawData = append(rawData, '\n')
|
||||
if len(parser.config.Devices) == 0 {
|
||||
return errors.New("Found no devices in configuration. Please add configuration at " + directory)
|
||||
}
|
||||
|
||||
if len(rawData) == 0 {
|
||||
logger.Log("No config data found. Write .yml config files in ~/.config/joyful")
|
||||
return nil
|
||||
}
|
||||
|
||||
return rawData
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateVirtualDevices will register any configured devices with type = virtual
|
||||
// using /dev/uinput, and return a map of those devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once, unless you want to create duplicate devices for some reason.
|
||||
func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices.Virtual {
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypeVirtual {
|
||||
continue
|
||||
}
|
||||
|
||||
vDevice, err := evdev.CreateDevice(
|
||||
fmt.Sprintf("joyful-%s", deviceConfig.Name),
|
||||
// TODO: who knows what these should actually be
|
||||
|
@ -95,12 +99,42 @@ func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice
|
|||
return deviceMap
|
||||
}
|
||||
|
||||
// ConnectPhysicalDevices will create InputDevices corresponding to any registered
|
||||
// devices with type = physical. It will also attempt to acquire exclusive access
|
||||
// to those devices, to prevent the same inputs from being read on multiple devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once.
|
||||
//
|
||||
// STUB: this function does not yet function.
|
||||
func (parser *ConfigParser) ConnectPhysicalDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypePhysical {
|
||||
continue
|
||||
}
|
||||
|
||||
vDevice, err := evdev.Open("/dev/input/foo")
|
||||
|
||||
if err != nil {
|
||||
logger.LogIfError(err, "Failed to open physical device")
|
||||
continue
|
||||
}
|
||||
|
||||
deviceMap[deviceConfig.Name] = vDevice
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
func makeButtons(numButtons int) []evdev.EvCode {
|
||||
if numButtons > 56 {
|
||||
numButtons = 56
|
||||
logger.Log("Limiting virtual device buttons to 56")
|
||||
}
|
||||
|
||||
|
||||
buttons := make([]evdev.EvCode, numButtons)
|
||||
|
||||
startCode := 0x120
|
||||
|
@ -110,8 +144,8 @@ func makeButtons(numButtons int) []evdev.EvCode {
|
|||
|
||||
if numButtons > 16 {
|
||||
startCode = 0x2c0
|
||||
for i := 0; i < numButtons - 16; i++ {
|
||||
buttons[16+i] = evdev.EvCode(startCode+i)
|
||||
for i := 0; i < numButtons-16; i++ {
|
||||
buttons[16+i] = evdev.EvCode(startCode + i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,4 +164,4 @@ func makeAxes(numAxes int) []evdev.EvCode {
|
|||
}
|
||||
|
||||
return axes
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue