apply settings for OS2L

This commit is contained in:
2025-11-13 16:00:50 +01:00
parent 18a3a716ef
commit c7d9f35080
6 changed files with 124 additions and 72 deletions

View File

@@ -180,7 +180,7 @@ func (f *FTDIFinder) GetPeripheralSettings(peripheralID string) (map[string]inte
}
// SetPeripheralSettings sets the peripheral settings
func (f *FTDIFinder) SetPeripheralSettings(peripheralID string, settings map[string]interface{}) error {
func (f *FTDIFinder) SetPeripheralSettings(ctx context.Context, peripheralID string, settings map[string]any) error {
// Return the specified peripheral
// peripheral, found := f.registeredPeripherals[peripheralID]
// if !found {

View File

@@ -60,7 +60,7 @@ func (f *OS2LFinder) RegisterPeripheral(ctx context.Context, peripheralData Peri
// Create a new OS2L peripheral
peripheral, err := NewOS2LPeripheral(peripheralData)
if err != nil {
return "", fmt.Errorf("unable to create the OS2L peripheral: %v", err)
return "", fmt.Errorf("unable to create the OS2L peripheral: %w", err)
}
// Set the event callback
peripheral.SetEventCallback(func(event any) {
@@ -79,21 +79,17 @@ func (f *OS2LFinder) RegisterPeripheral(ctx context.Context, peripheralData Peri
go func() {
defer f.wg.Done()
// Connect the OS2L peripheral
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusConnecting)
err = peripheral.Connect(ctx)
if err != nil {
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusDisconnected)
log.Err(err).Str("file", "OS2LFinder").Str("peripheralSN", peripheralData.SerialNumber).Msg("unable to connect the peripheral")
return
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusDeactivated)
// Peripheral connected, activate it
err = peripheral.Activate(ctx)
if err != nil {
log.Err(err).Str("file", "OS2LFinder").Str("peripheralSN", peripheralData.SerialNumber).Msg("unable to activate the OS2L peripheral")
return
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusActivated)
}()
// Emits the event in the hardware
@@ -114,14 +110,12 @@ func (f *OS2LFinder) UnregisterPeripheral(ctx context.Context, peripheralData Pe
log.Err(err).Str("sn", peripheralData.SerialNumber).Msg("unable to deactivate the peripheral")
return nil
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusDeactivated)
// Disconnecting peripheral
err = peripheral.Disconnect()
err = peripheral.Disconnect(ctx)
if err != nil {
log.Err(err).Str("sn", peripheralData.SerialNumber).Msg("unable to disconnect the peripheral")
return nil
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralData, PeripheralStatusDisconnected)
}
// The OS2L peripheral has gone
@@ -138,7 +132,7 @@ func (f *OS2LFinder) GetName() string {
}
// GetPeripheralSettings gets the peripheral settings
func (f *OS2LFinder) GetPeripheralSettings(peripheralID string) (map[string]interface{}, error) {
func (f *OS2LFinder) GetPeripheralSettings(peripheralID string) (map[string]any, error) {
// Return the specified peripheral
peripheral, found := f.saved[peripheralID]
if !found {
@@ -150,15 +144,16 @@ func (f *OS2LFinder) GetPeripheralSettings(peripheralID string) (map[string]inte
}
// SetPeripheralSettings sets the peripheral settings
func (f *OS2LFinder) SetPeripheralSettings(peripheralID string, settings map[string]interface{}) error {
func (f *OS2LFinder) SetPeripheralSettings(ctx context.Context, peripheralID string, settings map[string]any) error {
// Return the specified peripheral
peripheral, found := f.saved[peripheralID]
if !found {
log.Error().Str("file", "OS2LFinder").Str("peripheralID", peripheralID).Msg("unable to get this peripheral from the FTDI finder")
return fmt.Errorf("unable to found the peripheral")
}
log.Debug().Str("file", "OS2LFinder").Str("peripheralID", peripheralID).Msg("peripheral found by the FTDI finder")
return peripheral.SetSettings(settings)
// Set the peripheral settings
return peripheral.SetSettings(ctx, settings)
}
// Start starts the finder

View File

@@ -5,10 +5,12 @@ import (
"encoding/json"
"fmt"
"net"
"strings"
"sync"
"time"
"github.com/rs/zerolog/log"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
// OS2LMessage represents an OS2L message
@@ -35,14 +37,13 @@ type OS2LPeripheral struct {
// NewOS2LPeripheral creates a new OS2L peripheral
func NewOS2LPeripheral(peripheralData PeripheralInfo) (*OS2LPeripheral, error) {
log.Trace().Str("file", "OS2LPeripheral").Str("name", peripheralData.Name).Str("s/n", peripheralData.SerialNumber).Msg("OS2L peripheral created")
return &OS2LPeripheral{
peripheral := &OS2LPeripheral{
info: peripheralData,
serverIP: "127.0.0.1",
serverPort: 9995,
listener: nil,
eventCallback: nil,
}, nil
}
log.Trace().Str("file", "OS2LPeripheral").Str("name", peripheralData.Name).Str("s/n", peripheralData.SerialNumber).Msg("OS2L peripheral created")
return peripheral, peripheral.loadSettings(peripheralData.Settings)
}
// SetEventCallback sets the callback for returning events
@@ -50,15 +51,21 @@ func (p *OS2LPeripheral) SetEventCallback(eventCallback func(any)) {
p.eventCallback = eventCallback
}
// Connect connects the MIDI peripheral
// Connect connects the OS2L peripheral
func (p *OS2LPeripheral) Connect(ctx context.Context) error {
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusConnecting)
var err error
addr := net.TCPAddr{Port: p.serverPort, IP: net.ParseIP(p.serverIP)}
log.Debug().Any("addr", addr).Msg("parametres de connexion à la connexion")
p.listener, err = net.ListenTCP("tcp", &addr)
if err != nil {
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusDisconnected)
return fmt.Errorf("unable to set the OS2L TCP listener")
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusDeactivated)
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral connected")
return nil
}
@@ -78,14 +85,49 @@ func (p *OS2LPeripheral) handleMessage(raw []byte) error {
return nil
}
// loadSettings check and load the settings in the peripheral
func (p *OS2LPeripheral) loadSettings(settings map[string]any) error {
// Check if the IP exists
serverIP, found := settings["os2lIp"]
if !found {
// Set default IP address
serverIP = "127.0.0.1"
}
// Check if it is a string
ipSetting, ok := serverIP.(string)
if ok {
p.serverIP = ipSetting
} else {
return fmt.Errorf("The specified IP is not a string")
}
// Check if the port exists
serverPort, found := settings["os2lPort"]
if !found {
// Set default port
serverPort = 9995
}
switch v := serverPort.(type) {
case int:
p.serverPort = v
case float64:
p.serverPort = int(v) // JSON numbers are float64
default:
return fmt.Errorf("The specified port is not a number, got %T", serverPort)
}
return nil
}
// Disconnect disconnects the MIDI peripheral
func (p *OS2LPeripheral) Disconnect() error {
func (p *OS2LPeripheral) Disconnect(ctx context.Context) error {
// Close the TCP listener if not null
if p.listener != nil {
p.listener.Close()
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusDisconnected)
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral disconnected")
return nil
}
@@ -115,6 +157,9 @@ func (p *OS2LPeripheral) Activate(ctx context.Context) error {
if ne, ok := err.(net.Error); ok && ne.Timeout() {
continue
}
if strings.Contains(err.Error(), "use of closed network connection") || strings.Contains(err.Error(), "invalid argument") {
return
}
log.Err(err).Str("file", "OS2LPeripheral").Msg("unable to accept the connection")
continue
}
@@ -153,6 +198,8 @@ func (p *OS2LPeripheral) Activate(ctx context.Context) error {
}
}
}()
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusActivated)
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral activated")
return nil
@@ -169,37 +216,46 @@ func (p *OS2LPeripheral) Deactivate(ctx context.Context) error {
p.listenerCancel()
}
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), p.GetInfo(), PeripheralStatusDeactivated)
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral deactivated")
return nil
}
// SetSettings sets a specific setting for this peripheral
func (p *OS2LPeripheral) SetSettings(settings map[string]interface{}) error {
// Check if the IP exists
serverIP, found := settings["os2lIp"]
if !found {
return fmt.Errorf("Unable to find the OS2L server IP")
}
// Check if it is a string
ipSetting, ok := serverIP.(string)
if ok {
p.serverIP = ipSetting
} else {
return fmt.Errorf("The specified IP is not a string")
}
// Check if the port exists
serverPort, found := settings["os2lPort"]
if !found {
return fmt.Errorf("Unable to find the OS2L server port")
}
// Check if it is a float and convert to int
portFloat, ok := serverPort.(float64)
if ok {
p.serverPort = int(portFloat)
} else {
return fmt.Errorf("The specified port is not an int")
func (p *OS2LPeripheral) SetSettings(ctx context.Context, settings map[string]any) error {
err := p.loadSettings(settings)
if err != nil {
return fmt.Errorf("unable to load settings: %w", err)
}
// Reconnect the peripheral
p.wg.Add(1)
go func() {
defer p.wg.Done()
err := p.Deactivate(ctx)
if err != nil {
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to deactivate")
return
}
err = p.Disconnect(ctx)
if err != nil {
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to disconnect")
return
}
// Add a sleep to view changes
time.Sleep(500 * time.Millisecond)
err = p.Connect(ctx)
if err != nil {
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to connect")
return
}
err = p.Activate(ctx)
if err != nil {
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to activate")
return
}
}()
log.Info().Str("sn", p.GetInfo().SerialNumber).Msg("peripheral settings set")
return nil
}
@@ -209,8 +265,8 @@ func (p *OS2LPeripheral) SetDeviceProperty(context.Context, uint32, uint32, byte
}
// GetSettings gets the peripheral settings
func (p *OS2LPeripheral) GetSettings() map[string]interface{} {
return map[string]interface{}{
func (p *OS2LPeripheral) GetSettings() map[string]any {
return map[string]any{
"os2lIp": p.serverIP,
"os2lPort": p.serverPort,
}

View File

@@ -6,36 +6,36 @@ import "context"
type Peripheral interface {
Connect(context.Context) error // Connect the peripheral
SetEventCallback(func(any)) // Callback is called when an event is emitted from the peripheral
Disconnect() error // Disconnect the peripheral
Disconnect(context.Context) error // Disconnect the peripheral
Activate(context.Context) error // Activate the peripheral
Deactivate(context.Context) error // Deactivate the peripheral
SetSettings(map[string]interface{}) error // Set a peripheral setting
SetSettings(context.Context, map[string]any) error // Set a peripheral setting
SetDeviceProperty(context.Context, uint32, byte) error // Update a device property
WaitStop() error // Properly close the peripheral
GetInfo() PeripheralInfo // Get the peripheral information
GetSettings() map[string]interface{} // Get the peripheral settings
GetInfo() PeripheralInfo // Get the peripheral information
GetSettings() map[string]any // Get the peripheral settings
}
// PeripheralInfo represents a peripheral information
type PeripheralInfo struct {
Name string `yaml:"name"` // Name of the peripheral
SerialNumber string `yaml:"sn"` // S/N of the peripheral
ProtocolName string `yaml:"protocol"` // Protocol name of the peripheral
Settings map[string]interface{} `yaml:"settings"` // Peripheral settings
Name string `yaml:"name"` // Name of the peripheral
SerialNumber string `yaml:"sn"` // S/N of the peripheral
ProtocolName string `yaml:"protocol"` // Protocol name of the peripheral
Settings map[string]any `yaml:"settings"` // Peripheral settings
}
// PeripheralFinder represents how compatible peripheral drivers are implemented
type PeripheralFinder interface {
Initialize() error // Initializes the protocol
OnArrival(cb func(p PeripheralInfo)) // Callback function when a peripheral arrives
OnRemoval(cb func(p PeripheralInfo)) // Callback function when a peripheral goes away
Start(context.Context) error // Start the detection
WaitStop() error // Waiting for finder to close
ForceScan() // Explicitly scans for peripherals
RegisterPeripheral(context.Context, PeripheralInfo) (string, error) // Registers a new peripheral data
UnregisterPeripheral(context.Context, PeripheralInfo) error // Unregisters an existing peripheral
GetPeripheralSettings(string) (map[string]interface{}, error) // Gets the peripheral settings
SetPeripheralSettings(string, map[string]interface{}) error // Sets the peripheral settings
GetName() string // Get the name of the finder
Initialize() error // Initializes the protocol
OnArrival(cb func(p PeripheralInfo)) // Callback function when a peripheral arrives
OnRemoval(cb func(p PeripheralInfo)) // Callback function when a peripheral goes away
Start(context.Context) error // Start the detection
WaitStop() error // Waiting for finder to close
ForceScan() // Explicitly scans for peripherals
RegisterPeripheral(context.Context, PeripheralInfo) (string, error) // Registers a new peripheral data
UnregisterPeripheral(context.Context, PeripheralInfo) error // Unregisters an existing peripheral
GetPeripheralSettings(string) (map[string]any, error) // Gets the peripheral settings
SetPeripheralSettings(context.Context, string, map[string]any) error // Sets the peripheral settings
GetName() string // Get the name of the finder
}