generated from thinkode/modelRepository
improved log system
This commit is contained in:
@@ -11,6 +11,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,6 +26,7 @@ type FTDIDriver struct {
|
||||
|
||||
// NewFTDIDriver creates a new FTDI finder
|
||||
func NewFTDIDriver() *FTDIDriver {
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("FTDI driver created")
|
||||
return &FTDIDriver{
|
||||
peripherals: make(map[string]Peripheral),
|
||||
}
|
||||
@@ -32,9 +35,10 @@ func NewFTDIDriver() *FTDIDriver {
|
||||
// Initialize initializes the FTDI driver
|
||||
func (d *FTDIDriver) Initialize() error {
|
||||
if goRuntime.GOOS != "windows" {
|
||||
log.Error().Str("file", "FTDIDriver").Str("platform", goRuntime.GOOS).Msg("FTDI driver not compatible with your platform")
|
||||
return fmt.Errorf("<!> The FTDI driver is not compatible with your platform yet (%s)", goRuntime.GOOS)
|
||||
}
|
||||
fmt.Println("FTDI driver initialized")
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("FTDI driver initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -48,11 +52,10 @@ func (d *FTDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
|
||||
// Return the specified peripheral
|
||||
peripheral := d.peripherals[peripheralID]
|
||||
if peripheral == nil {
|
||||
fmt.Println("Unable to get the peripheral with the driver")
|
||||
log.Error().Str("file", "FTDIDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral from the FTDI driver")
|
||||
return nil, false
|
||||
}
|
||||
fmt.Println("Peripheral found by the FTDI driver")
|
||||
|
||||
log.Debug().Str("file", "FTDIDriver").Str("peripheralID", peripheralID).Msg("peripheral found by the FTDI driver")
|
||||
return peripheral, true
|
||||
}
|
||||
|
||||
@@ -61,6 +64,7 @@ var findFTDI []byte
|
||||
|
||||
// Scan scans the FTDI peripherals
|
||||
func (d *FTDIDriver) Scan(ctx context.Context) error {
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("FTDI scan triggered")
|
||||
time.Sleep(scanDelay)
|
||||
|
||||
// Create a temporary file
|
||||
@@ -69,61 +73,68 @@ func (d *FTDIDriver) Scan(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(tempFile.Name())
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("has created the FIND executable temp")
|
||||
|
||||
// Write the embedded executable to the temp file
|
||||
if _, err := tempFile.Write(findFTDI); err != nil {
|
||||
return err
|
||||
}
|
||||
tempFile.Close()
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("has written the FIND executable")
|
||||
|
||||
ftdiPeripherals := make(map[string]Peripheral)
|
||||
|
||||
finder := exec.Command(tempFile.Name())
|
||||
log.Trace().Str("file", "FTDIDriver").Msg("has executed the FIND executable")
|
||||
|
||||
stdout, err := finder.StdoutPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create the stdout pipe: %s", err)
|
||||
return fmt.Errorf("unable to create the stdout pipe: %s", err)
|
||||
}
|
||||
|
||||
stderr, err := finder.StderrPipe()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create the stderr pipe: %s", err)
|
||||
return fmt.Errorf("unable to create the stderr pipe: %s", err)
|
||||
}
|
||||
|
||||
err = finder.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to find FTDI devices: %s", err)
|
||||
return fmt.Errorf("unable to find FTDI devices: %s", err)
|
||||
}
|
||||
|
||||
scannerErr := bufio.NewScanner(stderr)
|
||||
for scannerErr.Scan() {
|
||||
return fmt.Errorf("Unable to find FTDI devices: %s", scannerErr.Text())
|
||||
return fmt.Errorf("unable to find FTDI devices: %s", scannerErr.Text())
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
deviceString := scanner.Text()
|
||||
peripheralString := scanner.Text()
|
||||
// The program output is like '0:1:2' where 0 is the location, 1 is the S/N and 2 is the name
|
||||
deviceInfo := strings.Split(deviceString, ":")
|
||||
peripheralInfo := strings.Split(peripheralString, ":")
|
||||
|
||||
fmt.Println("FTDI device: " + deviceString)
|
||||
log.Debug().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Str("peripheralSN", peripheralInfo[1]).Msg("new FTDI peripheral detected")
|
||||
// Convert the location to an integer
|
||||
location, err := strconv.Atoi(deviceInfo[0])
|
||||
location, err := strconv.Atoi(peripheralInfo[0])
|
||||
if err != nil {
|
||||
log.Warn().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Msg("no location provided for this FTDI peripheral")
|
||||
location = -1
|
||||
}
|
||||
// Add the peripheral to the temporary list
|
||||
peripheral, err := NewFTDIPeripheral(deviceInfo[2], deviceInfo[1], location)
|
||||
peripheral, err := NewFTDIPeripheral(peripheralInfo[2], peripheralInfo[1], location)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create the FTDI peripheral: %v", err)
|
||||
}
|
||||
ftdiPeripherals[deviceInfo[1]] = peripheral
|
||||
ftdiPeripherals[peripheralInfo[1]] = peripheral
|
||||
log.Trace().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Msg("successfully added the FTDI peripheral to the driver")
|
||||
}
|
||||
// Compare with the current peripherals to detect arrivals/removals
|
||||
removedList, addedList := comparePeripherals(d.peripherals, ftdiPeripherals)
|
||||
// Emit the events
|
||||
emitPeripheralsEvents(ctx, removedList, PeripheralRemoval)
|
||||
log.Info().Str("file", "FTDIDriver").Msg("FTDI remove list emitted to the front")
|
||||
emitPeripheralsEvents(ctx, addedList, PeripheralArrival)
|
||||
log.Info().Str("file", "FTDIDriver").Msg("FTDI add list emitted to the front")
|
||||
// Store the new peripherals list
|
||||
d.peripherals = ftdiPeripherals
|
||||
return nil
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
@@ -38,16 +40,19 @@ type FTDIPeripheral struct {
|
||||
|
||||
// NewFTDIPeripheral creates a new FTDI peripheral
|
||||
func NewFTDIPeripheral(name string, serialNumber string, location int) (*FTDIPeripheral, error) {
|
||||
log.Info().Str("file", "FTDIPeripheral").Str("name", name).Str("s/n", serialNumber).Int("location", location).Msg("FTDI peripheral created")
|
||||
// Create a temporary file
|
||||
tempFile, err := os.CreateTemp("", "dmxSender*.exe")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", serialNumber).Msg("FTDI sender temp created")
|
||||
|
||||
// Write the embedded executable to the temp file
|
||||
if _, err := tempFile.Write(dmxSender); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", serialNumber).Msg("FTDI sender written")
|
||||
|
||||
tempFile.Close()
|
||||
|
||||
@@ -65,35 +70,40 @@ func NewFTDIPeripheral(name string, serialNumber string, location int) (*FTDIPer
|
||||
// Connect connects the FTDI peripheral
|
||||
func (p *FTDIPeripheral) Connect() error {
|
||||
// Connect if no connection is already running
|
||||
fmt.Println(p.dmxSender)
|
||||
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("connecting FTDI peripheral...")
|
||||
if p.dmxSender == nil {
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("no instance of dmxSender for this FTDI")
|
||||
|
||||
// Executing the command
|
||||
p.dmxSender = exec.Command(p.programName, fmt.Sprintf("%d", p.location))
|
||||
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("no instance of dmxSender for this FTDI")
|
||||
|
||||
var err error
|
||||
p.stdout, err = p.dmxSender.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create the stdout pipe: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stdout pipe")
|
||||
return fmt.Errorf("unable to create the stdout pipe: %v", err)
|
||||
}
|
||||
|
||||
p.stdin, err = p.dmxSender.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create the stdin pipe: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stdin pipe")
|
||||
return fmt.Errorf("unable to create the stdin pipe: %v", err)
|
||||
}
|
||||
|
||||
p.stderr, err = p.dmxSender.StderrPipe()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create the stderr pipe: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stderr pipe")
|
||||
return fmt.Errorf("unable to create the stderr pipe: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(p.stderr)
|
||||
for scanner.Scan() {
|
||||
// Traitez chaque ligne lue depuis stderr
|
||||
fmt.Printf("Erreur : %s\n", scanner.Text())
|
||||
log.Err(fmt.Errorf(scanner.Text())).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error detected in dmx sender")
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Printf("Error reading from stderr: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error reading from stderr")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -102,17 +112,12 @@ func (p *FTDIPeripheral) Connect() error {
|
||||
defer p.wg.Done()
|
||||
err = p.dmxSender.Run()
|
||||
if err != nil {
|
||||
// Affiche l'erreur (cela inclut également les erreurs de retour du programme)
|
||||
fmt.Printf("Erreur lors de l'exécution : %v\n", err)
|
||||
|
||||
// Vérifie si l'erreur est liée au code de retour
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while execution of dmw sender")
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
// Récupère et affiche le code de retour
|
||||
fmt.Printf("Le programme s'est terminé avec le code : %d\n", exitError.ExitCode())
|
||||
fmt.Println(p.stderr)
|
||||
log.Warn().Str("file", "FTDIPeripheral").Int("exitCode", exitError.ExitCode()).Str("s/n", p.serialNumber).Msg("dmx sender exited with code")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Le programme s'est terminé avec succès.")
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmx sender exited successfully")
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -121,74 +126,72 @@ func (p *FTDIPeripheral) Connect() error {
|
||||
|
||||
// Disconnect disconnects the FTDI peripheral
|
||||
func (p *FTDIPeripheral) Disconnect() error {
|
||||
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("disconnecting FTDI peripheral...")
|
||||
if p.dmxSender != nil {
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI")
|
||||
_, err := io.WriteString(p.stdin, string([]byte{0x04, 0x00, 0x00, 0x00}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to disconnect: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender")
|
||||
return fmt.Errorf("unable to disconnect: %v", err)
|
||||
}
|
||||
p.stdin.Close()
|
||||
p.stdout.Close()
|
||||
p.dmxSender = nil
|
||||
err = os.Remove(p.programName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to delete the temporary file: %v", err)
|
||||
log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to delete the dmx sender temporary file")
|
||||
return fmt.Errorf("unable to delete the temporary file: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Unable to disconnect: not connected")
|
||||
// if p.dmxSender != nil {
|
||||
// err := p.dmxSender.Process.Kill()
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Unable to disconnect: %v", err)
|
||||
// }
|
||||
// p.stdin.Close()
|
||||
// p.stdout.Close()
|
||||
// p.dmxSender = nil
|
||||
// err = os.Remove(p.programName)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("Unable to delete the temporary file: %v", err)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
// return fmt.Errorf("Unable to disconnect: not connected")
|
||||
log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while disconnecting: not connected")
|
||||
return fmt.Errorf("unable to disconnect: not connected")
|
||||
}
|
||||
|
||||
// Activate activates the FTDI peripheral
|
||||
func (p *FTDIPeripheral) Activate() error {
|
||||
if p.dmxSender != nil {
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI")
|
||||
_, err := io.WriteString(p.stdin, string([]byte{0x01, 0x00, 0x00, 0x00}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to activate: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender")
|
||||
return fmt.Errorf("unable to activate: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Unable to activate: not connected")
|
||||
log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while activating: not connected")
|
||||
return fmt.Errorf("unable to activate: not connected")
|
||||
}
|
||||
|
||||
// Deactivate deactivates the FTDI peripheral
|
||||
func (p *FTDIPeripheral) Deactivate() error {
|
||||
if p.dmxSender != nil {
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI")
|
||||
_, err := io.WriteString(p.stdin, string([]byte{0x02, 0x00, 0x00, 0x00}))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to deactivate: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender")
|
||||
return fmt.Errorf("unable to deactivate: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Unable to deactivate: not connected")
|
||||
log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while deactivating: not connected")
|
||||
return fmt.Errorf("unable to deactivate: not connected")
|
||||
}
|
||||
|
||||
// SetDeviceProperty sends a command to the specified device
|
||||
func (p *FTDIPeripheral) SetDeviceProperty(uint32, channelNumber uint32, channelValue byte) error {
|
||||
if p.dmxSender != nil {
|
||||
fmt.Println(channelValue)
|
||||
log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI")
|
||||
commandString := []byte{0x03, 0x01, 0x00, 0xff, 0x03, 0x02, 0x00, channelValue}
|
||||
_, err := io.WriteString(p.stdin, string(commandString))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to set device property: %v", err)
|
||||
log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender")
|
||||
return fmt.Errorf("unable to set device property: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Unable to set device property: not connected")
|
||||
log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while setting device property: not connected")
|
||||
return fmt.Errorf("unable to set device property: not connected")
|
||||
}
|
||||
|
||||
// GetInfo gets all the peripheral information
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mattrtaylor/go-rtmidi"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// MIDIDriver represents how the protocol is defined
|
||||
@@ -17,6 +18,7 @@ type MIDIDriver struct {
|
||||
|
||||
// NewMIDIDriver creates a new DMXUSB protocol
|
||||
func NewMIDIDriver() *MIDIDriver {
|
||||
log.Trace().Str("file", "MIDIDriver").Msg("MIDI driver created")
|
||||
return &MIDIDriver{
|
||||
peripherals: make(map[string]Peripheral),
|
||||
}
|
||||
@@ -24,7 +26,7 @@ func NewMIDIDriver() *MIDIDriver {
|
||||
|
||||
// Initialize initializes the MIDI driver
|
||||
func (d *MIDIDriver) Initialize() error {
|
||||
fmt.Println("MIDI driver initialized")
|
||||
log.Trace().Str("file", "MIDIDriver").Msg("MIDI driver initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,10 +38,12 @@ func (d *MIDIDriver) GetName() string {
|
||||
// GetPeripheral gets the peripheral that correspond to the specified ID
|
||||
func (d *MIDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
|
||||
// Return the specified peripheral
|
||||
peripheral := d.peripherals[peripheralID]
|
||||
if peripheral == nil {
|
||||
peripheral, found := d.peripherals[peripheralID]
|
||||
if !found {
|
||||
log.Error().Str("file", "MIDIDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral in the MIDI driver")
|
||||
return nil, false
|
||||
}
|
||||
log.Trace().Str("file", "MIDIDriver").Str("peripheralID", peripheralID).Msg("MIDI peripheral found in the driver")
|
||||
return peripheral, true
|
||||
}
|
||||
|
||||
@@ -67,28 +71,35 @@ func splitStringAndNumber(input string) (string, int, error) {
|
||||
// Scan scans the interfaces compatible with the MIDI protocol
|
||||
func (d *MIDIDriver) Scan(ctx context.Context) error {
|
||||
midiPeripherals := make(map[string]Peripheral)
|
||||
fmt.Println("Opening MIDI scanner port...")
|
||||
log.Trace().Str("file", "MIDIDriver").Msg("opening MIDI scanner port...")
|
||||
midiScanner, err := rtmidi.NewMIDIInDefault()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error when opening the MIDI scanner: %s", err)
|
||||
log.Err(err).Str("file", "MIDIDriver").Msg("unable to open the MIDI scanner port...")
|
||||
return fmt.Errorf("unable to open the MIDI scanner: %s", err)
|
||||
}
|
||||
defer midiScanner.Close()
|
||||
fmt.Println("Scanning MIDI devices...")
|
||||
midiScanner.SetCallback(func(m rtmidi.MIDIIn, b []byte, f float64) {
|
||||
|
||||
})
|
||||
log.Trace().Str("file", "MIDIDriver").Msg("scanning MIDI peripherals...")
|
||||
devicesCount, err := midiScanner.PortCount()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error when scanning MIDI devices: %s", err)
|
||||
log.Err(err).Str("file", "MIDIDriver").Msg("unable to scan MIDI peripherals...")
|
||||
return fmt.Errorf("unable to scan MIDI peripherals: %s", err)
|
||||
}
|
||||
for i := 0; i < devicesCount; i++ {
|
||||
portName, err := midiScanner.PortName(i)
|
||||
if err != nil {
|
||||
log.Warn().Str("file", "MIDIPeripheral").Msg("found peripheral without a correct name, set it to unknown")
|
||||
portName = "Unknown device 0"
|
||||
}
|
||||
// Separate data
|
||||
name, location, err := splitStringAndNumber(portName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to get information from the string: %s", err)
|
||||
log.Err(err).Str("file", "MIDIDriver").Str("description", portName).Msg("invalid peripheral description")
|
||||
return fmt.Errorf("invalid pripheral description: %s", err)
|
||||
}
|
||||
fmt.Printf("New MIDI device found: %s on %i\n", name, location)
|
||||
log.Info().Str("file", "MIDIDriver").Str("name", name).Int("location", location).Msg("MIDI peripheral found")
|
||||
// Add the peripheral to the temporary list
|
||||
sn := strings.ToLower(strings.Replace(name, " ", "_", -1))
|
||||
midiPeripherals[sn] = NewMIDIPeripheral(name, location, sn)
|
||||
@@ -97,7 +108,9 @@ func (d *MIDIDriver) Scan(ctx context.Context) error {
|
||||
removedList, addedList := comparePeripherals(d.peripherals, midiPeripherals)
|
||||
// Emit the events
|
||||
emitPeripheralsEvents(ctx, removedList, PeripheralRemoval)
|
||||
log.Info().Str("file", "MIDIDriver").Msg("MIDI remove list emitted to the front")
|
||||
emitPeripheralsEvents(ctx, addedList, PeripheralArrival)
|
||||
log.Info().Str("file", "MIDIDriver").Msg("MIDI add list emitted to the front")
|
||||
// Store the new peripherals list
|
||||
d.peripherals = midiPeripherals
|
||||
return nil
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package hardware
|
||||
|
||||
import "github.com/rs/zerolog/log"
|
||||
|
||||
// MIDIPeripheral contains the data of a MIDI peripheral
|
||||
type MIDIPeripheral struct {
|
||||
name string // The name of the peripheral
|
||||
@@ -9,6 +11,7 @@ type MIDIPeripheral struct {
|
||||
|
||||
// NewMIDIPeripheral creates a new MIDI peripheral
|
||||
func NewMIDIPeripheral(name string, location int, serialNumber string) *MIDIPeripheral {
|
||||
log.Trace().Str("file", "MIDIPeripheral").Str("name", name).Str("s/n", serialNumber).Int("location", location).Msg("MIDI peripheral created")
|
||||
return &MIDIPeripheral{
|
||||
name: name,
|
||||
location: location,
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// OS2LDriver represents how the protocol is defined
|
||||
@@ -14,6 +16,7 @@ type OS2LDriver struct {
|
||||
|
||||
// NewOS2LDriver creates a new OS2L driver
|
||||
func NewOS2LDriver() *OS2LDriver {
|
||||
log.Trace().Str("file", "OS2LDriver").Msg("OS2L driver created")
|
||||
return &OS2LDriver{
|
||||
peripherals: make(map[string]Peripheral),
|
||||
}
|
||||
@@ -21,7 +24,7 @@ func NewOS2LDriver() *OS2LDriver {
|
||||
|
||||
// Initialize initializes the MIDI driver
|
||||
func (d *OS2LDriver) Initialize() error {
|
||||
fmt.Println("OS2L driver initialized")
|
||||
log.Trace().Str("file", "OS2LDriver").Msg("OS2L driver initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -29,14 +32,17 @@ func (d *OS2LDriver) Initialize() error {
|
||||
func (d *OS2LDriver) CreatePeripheral(ctx context.Context) (Peripheral, error) {
|
||||
// Create a random serial number for this peripheral
|
||||
randomSerialNumber := strings.ToUpper(fmt.Sprintf("%08x", rand.Intn(1<<32)))
|
||||
log.Trace().Str("file", "OS2LDriver").Str("serialNumber", randomSerialNumber).Msg("OS2L peripheral created")
|
||||
peripheral := NewOS2LPeripheral("OS2L", randomSerialNumber)
|
||||
d.peripherals[randomSerialNumber] = peripheral
|
||||
log.Info().Str("file", "OS2LDriver").Str("serialNumber", randomSerialNumber).Msg("OS2L peripheral created and registered")
|
||||
return peripheral, nil
|
||||
}
|
||||
|
||||
// RemovePeripheral removes an OS2L dev
|
||||
func (d *OS2LDriver) RemovePeripheral(serialNumber string) error {
|
||||
delete(d.peripherals, serialNumber)
|
||||
log.Info().Str("file", "OS2LDriver").Str("serialNumber", serialNumber).Msg("OS2L peripheral removed")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -48,10 +54,12 @@ func (d *OS2LDriver) GetName() string {
|
||||
// GetPeripheral gets the peripheral that correspond to the specified ID
|
||||
func (d *OS2LDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
|
||||
// Return the specified peripheral
|
||||
peripheral := d.peripherals[peripheralID]
|
||||
if peripheral == nil {
|
||||
peripheral, found := d.peripherals[peripheralID]
|
||||
if !found {
|
||||
log.Error().Str("file", "OS2LDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral in the OS2L driver")
|
||||
return nil, false
|
||||
}
|
||||
log.Trace().Str("file", "OS2LDriver").Str("peripheralID", peripheralID).Msg("OS2L peripheral found in the driver")
|
||||
return peripheral, true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package hardware
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// OS2LPeripheral contains the data of an OS2L peripheral
|
||||
type OS2LPeripheral struct {
|
||||
@@ -10,6 +12,7 @@ type OS2LPeripheral struct {
|
||||
|
||||
// NewOS2LPeripheral creates a new OS2L peripheral
|
||||
func NewOS2LPeripheral(name string, serialNumber string) *OS2LPeripheral {
|
||||
log.Trace().Str("file", "OS2LPeripheral").Str("name", name).Str("s/n", serialNumber).Msg("OS2L peripheral created")
|
||||
return &OS2LPeripheral{
|
||||
name: name,
|
||||
serialNumber: serialNumber,
|
||||
@@ -18,25 +21,25 @@ func NewOS2LPeripheral(name string, serialNumber string) *OS2LPeripheral {
|
||||
|
||||
// Connect connects the MIDI peripheral
|
||||
func (p *OS2LPeripheral) Connect() error {
|
||||
fmt.Println("OS2L peripheral connected")
|
||||
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral connected")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disconnect disconnects the MIDI peripheral
|
||||
func (p *OS2LPeripheral) Disconnect() error {
|
||||
fmt.Println("OS2L peripheral disconnected")
|
||||
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral disconnected")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Activate activates the MIDI peripheral
|
||||
func (p *OS2LPeripheral) Activate() error {
|
||||
fmt.Println("OS2L peripheral activated")
|
||||
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral activated")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deactivate deactivates the MIDI peripheral
|
||||
func (p *OS2LPeripheral) Deactivate() error {
|
||||
fmt.Println("OS2L peripheral deactivated")
|
||||
log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral deactivated")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/lxn/win"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"golang.org/x/sys/windows"
|
||||
@@ -37,6 +39,7 @@ type HardwareManager struct {
|
||||
|
||||
// NewHardwareManager creates a new HardwareManager
|
||||
func NewHardwareManager() *HardwareManager {
|
||||
log.Trace().Str("package", "hardware").Msg("Hardware instance created")
|
||||
return &HardwareManager{
|
||||
drivers: make(map[string]PeripheralDriver),
|
||||
peripherals: make([]Peripheral, 0),
|
||||
@@ -44,13 +47,17 @@ func NewHardwareManager() *HardwareManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts to finding new device events
|
||||
// Start starts to find new peripheral events
|
||||
func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
cb := windows.NewCallback(h.wndProc)
|
||||
log.Trace().Str("file", "hardware").Msg("wndProc callback set")
|
||||
|
||||
inst := win.GetModuleHandle(nil)
|
||||
cn, err := syscall.UTF16PtrFromString("DMXConnect device watcher")
|
||||
log.Trace().Str("file", "hardware").Msg("got windows API instance")
|
||||
|
||||
cn, err := syscall.UTF16PtrFromString("DMXConnect peripheral watcher")
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "hardware").Msg("failed to convert window class name to UTF16")
|
||||
return fmt.Errorf("failed to convert window class name to UTF16: %w", err)
|
||||
}
|
||||
wc := win.WNDCLASSEX{
|
||||
@@ -58,12 +65,18 @@ func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
LpfnWndProc: cb,
|
||||
LpszClassName: cn,
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Msg("windows API class created")
|
||||
|
||||
wc.CbSize = uint32(unsafe.Sizeof(wc))
|
||||
if win.RegisterClassEx(&wc) == 0 {
|
||||
log.Err(syscall.GetLastError()).Str("file", "hardware").Msg("failed to register window class")
|
||||
return fmt.Errorf("failed to register window class: %w", syscall.GetLastError())
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Msg("window class registered")
|
||||
|
||||
wName, err := syscall.UTF16PtrFromString("usbevent.exe")
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "hardware").Msg("failed to convert window class name to UTF16")
|
||||
return fmt.Errorf("failed to convert window name to UTF16: %w", err)
|
||||
}
|
||||
wdw := win.CreateWindowEx(
|
||||
@@ -80,14 +93,18 @@ func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
wc.HInstance,
|
||||
nil)
|
||||
if wdw == 0 {
|
||||
log.Err(syscall.GetLastError()).Str("file", "hardware").Msg("failed to create window")
|
||||
return fmt.Errorf("failed to create window: %w", syscall.GetLastError())
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Msg("window created successfully")
|
||||
|
||||
_ = win.ShowWindow(wdw, win.SW_HIDE)
|
||||
win.UpdateWindow(wdw)
|
||||
log.Trace().Str("file", "hardware").Msg("window shown and updated")
|
||||
|
||||
// To continuously get the devices events from Windows
|
||||
go func() {
|
||||
defer log.Debug().Str("file", "hardware").Msg("peripheral watcher goroutine exited")
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -105,13 +122,17 @@ func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
|
||||
// To handle the peripheral changed
|
||||
go func() {
|
||||
defer log.Debug().Str("file", "hardware").Msg("peripheral getter goroutine exited")
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-h.deviceChangedEvent:
|
||||
fmt.Println("This is the list of devices")
|
||||
h.Scan(ctx)
|
||||
log.Debug().Str("file", "hardware").Msg("peripheral change event, triggering scan...")
|
||||
err := h.Scan(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "hardware").Msg("unable to scan peripherals")
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -122,26 +143,29 @@ func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
func (h *HardwareManager) GetDriver(driverName string) (PeripheralDriver, error) {
|
||||
driver, exists := h.drivers[driverName]
|
||||
if !exists {
|
||||
log.Error().Str("file", "hardware").Str("driverName", driverName).Msg("unable to get the driver")
|
||||
return nil, fmt.Errorf("Unable to locate the '%s' driver", driverName)
|
||||
}
|
||||
log.Debug().Str("file", "hardware").Str("driverName", driverName).Msg("got driver")
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
// RegisterDriver registers a new peripherals driver
|
||||
func (h *HardwareManager) RegisterDriver(driver PeripheralDriver) {
|
||||
h.drivers[driver.GetName()] = driver
|
||||
fmt.Printf("Success registered the %s driver\n", driver.GetName())
|
||||
log.Info().Str("file", "hardware").Str("driverName", driver.GetName()).Msg("driver registered")
|
||||
}
|
||||
|
||||
// GetPeripheral gets the peripheral object from the parent driver
|
||||
func (h *HardwareManager) GetPeripheral(driverName string, peripheralID string) (Peripheral, bool) {
|
||||
// Get the driver
|
||||
parentDriver := h.drivers[driverName]
|
||||
parentDriver, found := h.drivers[driverName]
|
||||
// If no driver found, return false
|
||||
if parentDriver == nil {
|
||||
fmt.Println("Unable to get the driver")
|
||||
if !found {
|
||||
log.Error().Str("file", "hardware").Str("driverName", driverName).Msg("unable to get the driver")
|
||||
return nil, false
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Str("driverName", parentDriver.GetName()).Msg("driver got")
|
||||
// Contact the driver to get the device
|
||||
return parentDriver.GetPeripheral(peripheralID)
|
||||
}
|
||||
@@ -149,14 +173,15 @@ func (h *HardwareManager) GetPeripheral(driverName string, peripheralID string)
|
||||
// Scan scans all the peripherals for the registered finders
|
||||
func (h *HardwareManager) Scan(ctx context.Context) error {
|
||||
if len(h.drivers) == 0 {
|
||||
return fmt.Errorf("No peripherals driver registered")
|
||||
log.Warn().Str("file", "hardware").Msg("no driver registered")
|
||||
return fmt.Errorf("no driver registered")
|
||||
}
|
||||
for _, driver := range h.drivers {
|
||||
driverCopy := driver
|
||||
go func() {
|
||||
err := driverCopy.Scan(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to scan peripherals with the %s driver: %s\n", driverCopy.GetName(), err)
|
||||
log.Err(err).Str("file", "hardware").Str("driverName", driverCopy.GetName()).Msg("unable to scan peripheral")
|
||||
return
|
||||
}
|
||||
}()
|
||||
@@ -170,9 +195,10 @@ func (h *HardwareManager) wndProc(hwnd windows.HWND, msg uint32, wParam, lParam
|
||||
// Trigger the devices scan when the last DEVICE_CHANGE event is received
|
||||
if debounceTimer != nil {
|
||||
debounceTimer.Stop()
|
||||
log.Trace().Str("file", "hardware").Msg("scan debounce timer stopped")
|
||||
}
|
||||
debounceTimer = time.AfterFunc(debounceDuration, func() {
|
||||
fmt.Printf("Devices list has changed, refresh the devices list\n")
|
||||
log.Debug().Str("file", "hardware").Msg("peripheral changed")
|
||||
h.deviceChangedEvent <- struct{}{}
|
||||
})
|
||||
}
|
||||
@@ -183,6 +209,7 @@ func (h *HardwareManager) wndProc(hwnd windows.HWND, msg uint32, wParam, lParam
|
||||
func emitPeripheralsEvents(ctx context.Context, peripheralsList map[string]Peripheral, peripheralEvent PeripheralEvent) {
|
||||
for _, peripheral := range peripheralsList {
|
||||
runtime.EventsEmit(ctx, string(peripheralEvent), peripheral.GetInfo())
|
||||
log.Trace().Str("file", "hardware").Str("event", string(peripheralEvent)).Msg("emit peripheral event")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,9 +222,11 @@ func comparePeripherals(oldPeripherals map[string]Peripheral, newPeripherals map
|
||||
for key, value := range oldPeripherals {
|
||||
oldList[key] = value
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Any("oldList", oldList).Msg("peripheral oldList comparison")
|
||||
for key, value := range newPeripherals {
|
||||
newList[key] = value
|
||||
}
|
||||
log.Trace().Str("file", "hardware").Any("newList", newList).Msg("peripheral newList comparison")
|
||||
// Remove in these lists all the commons peripherals
|
||||
for key := range newList {
|
||||
if _, exists := oldList[key]; exists {
|
||||
@@ -206,7 +235,7 @@ func comparePeripherals(oldPeripherals map[string]Peripheral, newPeripherals map
|
||||
}
|
||||
}
|
||||
// Now the old list contains the removed peripherals, and the new list contains the added peripherals
|
||||
fmt.Printf("%s\n", oldList)
|
||||
fmt.Printf("%s\n", newList)
|
||||
log.Trace().Str("file", "hardware").Any("oldList", oldList).Msg("peripheral oldList computed")
|
||||
log.Trace().Str("file", "hardware").Any("newList", newList).Msg("peripheral newList computed")
|
||||
return oldList, newList
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user