generated from thinkode/modelRepository
fixed tooltip
This commit is contained in:
190
hardware/hardware.go
Normal file
190
hardware/hardware.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package hardware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/lxn/win"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// PeripheralEvent is trigger by the finders when the scan is complete
|
||||
type PeripheralEvent string
|
||||
|
||||
const (
|
||||
// PeripheralArrival is triggerd when a peripheral has been connected to the system
|
||||
PeripheralArrival PeripheralEvent = "PERIPHERAL_ARRIVAL"
|
||||
// PeripheralRemoval is triggered when a peripheral has been disconnected from the system
|
||||
PeripheralRemoval PeripheralEvent = "PERIPHERAL_REMOVAL"
|
||||
debounceDuration = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
var (
|
||||
debounceTimer *time.Timer
|
||||
)
|
||||
|
||||
// HardwareManager is the class who manages the hardware
|
||||
type HardwareManager struct {
|
||||
finders []PeripheralFinder // The list of peripherals finders
|
||||
peripherals []Peripheral // The current list of peripherals
|
||||
deviceChangedEvent chan struct{} // The event when the devices list changed
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// NewHardwareManager creates a new HardwareManager
|
||||
func NewHardwareManager() *HardwareManager {
|
||||
return &HardwareManager{
|
||||
finders: make([]PeripheralFinder, 0),
|
||||
peripherals: make([]Peripheral, 0),
|
||||
deviceChangedEvent: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts to finding new device events
|
||||
func (h *HardwareManager) Start(ctx context.Context) error {
|
||||
cb := windows.NewCallback(h.wndProc)
|
||||
|
||||
inst := win.GetModuleHandle(nil)
|
||||
cn, err := syscall.UTF16PtrFromString("DMXConnect device watcher")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert window class name to UTF16: %w", err)
|
||||
}
|
||||
wc := win.WNDCLASSEX{
|
||||
HInstance: inst,
|
||||
LpfnWndProc: cb,
|
||||
LpszClassName: cn,
|
||||
}
|
||||
wc.CbSize = uint32(unsafe.Sizeof(wc))
|
||||
if win.RegisterClassEx(&wc) == 0 {
|
||||
return fmt.Errorf("failed to register window class: %w", syscall.GetLastError())
|
||||
}
|
||||
wName, err := syscall.UTF16PtrFromString("usbevent.exe")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert window name to UTF16: %w", err)
|
||||
}
|
||||
wdw := win.CreateWindowEx(
|
||||
0,
|
||||
wc.LpszClassName,
|
||||
wName,
|
||||
win.WS_MINIMIZE|win.WS_OVERLAPPEDWINDOW,
|
||||
win.CW_USEDEFAULT,
|
||||
win.CW_USEDEFAULT,
|
||||
100,
|
||||
100,
|
||||
0,
|
||||
0,
|
||||
wc.HInstance,
|
||||
nil)
|
||||
if wdw == 0 {
|
||||
return fmt.Errorf("failed to create window: %w", syscall.GetLastError())
|
||||
}
|
||||
|
||||
_ = win.ShowWindow(wdw, win.SW_HIDE)
|
||||
win.UpdateWindow(wdw)
|
||||
|
||||
// To continuously get the devices events from Windows
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
var msg win.MSG
|
||||
got := win.GetMessage(&msg, win.HWND(windows.HWND(wdw)), 0, 0)
|
||||
if got == 0 {
|
||||
win.TranslateMessage(&msg)
|
||||
win.DispatchMessage(&msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// To handle the peripheral changed
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-h.deviceChangedEvent:
|
||||
fmt.Println("This is the list of devices")
|
||||
h.Scan(ctx)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterFinder registers a new peripherals finder
|
||||
func (h *HardwareManager) RegisterFinder(finder PeripheralFinder) {
|
||||
h.finders = append(h.finders, finder)
|
||||
fmt.Printf("Success registered the %s finder\n", finder.GetName())
|
||||
}
|
||||
|
||||
// Scan scans all the peripherals for the registered finders
|
||||
func (h *HardwareManager) Scan(ctx context.Context) error {
|
||||
if len(h.finders) == 0 {
|
||||
return fmt.Errorf("No peripherals finder registered")
|
||||
}
|
||||
for _, finder := range h.finders {
|
||||
finder := finder
|
||||
go func() {
|
||||
err := finder.Scan(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to scan peripherals with the %s finder: %s\n", finder.GetName(), err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HardwareManager) wndProc(hwnd windows.HWND, msg uint32, wParam, lParam uintptr) uintptr {
|
||||
switch msg {
|
||||
case win.WM_DEVICECHANGE:
|
||||
// Trigger the devices scan when the last DEVICE_CHANGE event is received
|
||||
if debounceTimer != nil {
|
||||
debounceTimer.Stop()
|
||||
}
|
||||
debounceTimer = time.AfterFunc(debounceDuration, func() {
|
||||
fmt.Printf("Devices list has changed, refresh the devices list\n")
|
||||
h.deviceChangedEvent <- struct{}{}
|
||||
})
|
||||
}
|
||||
return win.DefWindowProc(win.HWND(hwnd), msg, wParam, lParam)
|
||||
}
|
||||
|
||||
// peripheralsList emits a peripheral event
|
||||
func emitPeripheralsEvents(ctx context.Context, peripheralsList map[string]Peripheral, peripheralEvent PeripheralEvent) {
|
||||
for _, peripheral := range peripheralsList {
|
||||
runtime.EventsEmit(ctx, string(peripheralEvent), peripheral.GetInfo())
|
||||
}
|
||||
}
|
||||
|
||||
// comparePeripherals compares the peripherals to determine which has been inserted or removed
|
||||
func comparePeripherals(oldPeripherals map[string]Peripheral, newPeripherals map[string]Peripheral) (map[string]Peripheral, map[string]Peripheral) {
|
||||
// Duplicate the lists
|
||||
oldList := make(map[string]Peripheral)
|
||||
newList := make(map[string]Peripheral)
|
||||
|
||||
for key, value := range oldPeripherals {
|
||||
oldList[key] = value
|
||||
}
|
||||
for key, value := range newPeripherals {
|
||||
newList[key] = value
|
||||
}
|
||||
// Remove in these lists all the commons peripherals
|
||||
for key := range newList {
|
||||
if _, exists := oldList[key]; exists {
|
||||
delete(oldList, key)
|
||||
delete(newList, key)
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
return oldList, newList
|
||||
}
|
||||
Reference in New Issue
Block a user