package hardware import ( "context" "errors" "fmt" "sync" "github.com/rs/zerolog/log" ) // Manager is the class who manages the hardware type Manager struct { mu sync.Mutex wg sync.WaitGroup providers map[string]Provider // The map of endpoints providers devices map[string]Device // The map of devices DetectedEndpoints map[string]Endpoint // The current list of endpoints SavedEndpoints map[string]EndpointInfo // The list of stored endpoints } // NewManager creates a new hardware manager func NewManager() *Manager { log.Trace().Str("package", "hardware").Msg("Hardware instance created") return &Manager{ providers: make(map[string]Provider, 0), devices: make(map[string]Device, 0), DetectedEndpoints: make(map[string]Endpoint, 0), SavedEndpoints: make(map[string]EndpointInfo, 0), } } // Start starts to find new endpoint events func (h *Manager) Start(ctx context.Context) error { for providerName, provider := range h.providers { // Initialize the provider err := provider.Initialize() if err != nil { log.Err(err).Str("file", "hardware").Str("providerName", providerName).Msg("unable to initialize provider") return err } // Set callback functions provider.OnArrival(h.OnEndpointArrival) provider.OnRemoval(h.OnEndpointRemoval) // Start the provider err = provider.Start(ctx) if err != nil { log.Err(err).Str("file", "hardware").Str("providerName", providerName).Msg("unable to start provider") return err } } return nil } // WaitStop stops the hardware manager func (h *Manager) WaitStop() error { log.Trace().Str("file", "hardware").Msg("closing the hardware manager") // Stop each provider var errs []error for name, f := range h.providers { if err := f.WaitStop(); err != nil { errs = append(errs, fmt.Errorf("%s: %w", name, err)) } } // Wait for all the endpoints to close log.Trace().Str("file", "MIDIProvider").Msg("closing all MIDI endpoints") for registeredEndpointSN, registeredEndpoint := range h.DetectedEndpoints { err := registeredEndpoint.WaitStop() if err != nil { errs = append(errs, fmt.Errorf("%s: %w", registeredEndpointSN, err)) } } // Wait for goroutines to finish h.wg.Wait() // Returning errors if len(errs) > 0 { return errors.Join(errs...) } log.Info().Str("file", "hardware").Msg("hardware manager stopped") return nil }