package services import ( "sync" "voicesnap/internal/engine" "voicesnap/internal/model" "voicesnap/internal/paths" "github.com/wailsapp/wails/v3/pkg/application" ) // EngineService provides engine status and model management to the frontend. type EngineService struct { app *application.App initCallback func() mu sync.RWMutex status string hardwareInfo string lastError string } func NewEngineService() *EngineService { return &EngineService{status: "loading"} } // ModelExists returns true if the ASR model files are present. func (s *EngineService) ModelExists() bool { return engine.ModelExists() } func (s *EngineService) GetStatus() map[string]interface{} { s.mu.RLock() defer s.mu.RUnlock() return map[string]interface{}{ "status": s.status, "hardwareInfo": s.hardwareInfo, "error": s.lastError, } } func (s *EngineService) SetStatus(status, hardwareInfo, lastError string) { s.mu.Lock() defer s.mu.Unlock() s.status = status s.hardwareInfo = hardwareInfo s.lastError = lastError } // DownloadModel downloads the ASR model with progress events. func (s *EngineService) DownloadModel(primaryURL, fallbackURL string) error { err := model.Download(primaryURL, fallbackURL, paths.ModelsRoot(), func(percent float64, downloaded, total int64) { if s.app != nil { s.app.Event.Emit("model:download-progress", map[string]interface{}{ "percent": percent, "downloaded": downloaded, "total": total, }) } }) if err != nil { return err } if s.initCallback != nil { go s.initCallback() } return nil } // SetInitCallback sets the callback to re-initialize the engine after model download. func (s *EngineService) SetInitCallback(cb func()) { s.initCallback = cb } // SetApp sets the Wails app reference for event emission. func (s *EngineService) SetApp(app *application.App) { s.app = app }