From 4e7591ebb1294f611e7b85082be55313dd53820f Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Wed, 03 Jun 2026 13:25:19 +0800
Subject: [PATCH] Implement Round 3 Moonshine English model

---
 privatevoice.src/app.go |   40 ++++++++++++++++++++++++++++++----------
 1 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/privatevoice.src/app.go b/privatevoice.src/app.go
index 8a39b1e..e642b13 100755
--- a/privatevoice.src/app.go
+++ b/privatevoice.src/app.go
@@ -48,6 +48,7 @@
 	cfg      *config.Config
 	recorder *audio.Recorder
 	eng      engine.Engine
+	engineMu sync.Mutex
 	hk       hotkey.Listener
 	paster   input.Paster
 	history  *history.Store
@@ -597,7 +598,17 @@
 		return
 	}
 
-	text, err := a.eng.Recognize(samples)
+	a.engineMu.Lock()
+	eng := a.eng
+	if eng == nil {
+		a.engineMu.Unlock()
+		logger.Error("Recognition skipped: engine not ready")
+		a.indicator.SetStatus(overlay.StatusError, "引擎未就绪")
+		a.delayedHideIf(autoHide, 2000)
+		return
+	}
+	text, err := eng.Recognize(samples)
+	a.engineMu.Unlock()
 	if err != nil {
 		logger.Error("Recognition failed: %v", err)
 		a.indicator.SetStatus(overlay.StatusError, "错误")
@@ -687,6 +698,7 @@
 	eng, err := engine.New()
 	if err != nil {
 		logger.Error("Engine initialization failed: %v", err)
+		a.replaceEngine(nil)
 		status := "need_model"
 		if modelExists {
 			status = "error"
@@ -701,9 +713,7 @@
 		return
 	}
 
-	a.mu.Lock()
-	a.eng = eng
-	a.mu.Unlock()
+	a.replaceEngine(eng)
 
 	logger.Info("ASR engine ready: %s", eng.HardwareInfo())
 	if a.engineService != nil {
@@ -728,6 +738,20 @@
 	a.indicator.SetStatus(overlay.StatusReady, hotkeyReadyText(keyName, hotkeyMode))
 	a.indicator.Show()
 	a.delayedHideIf(autoHide, 2000)
+}
+
+func (a *App) replaceEngine(eng engine.Engine) {
+	a.engineMu.Lock()
+	defer a.engineMu.Unlock()
+
+	a.mu.Lock()
+	old := a.eng
+	a.eng = eng
+	a.mu.Unlock()
+
+	if old != nil && old != eng {
+		old.Close()
+	}
 }
 
 func hotkeyReadyText(keyName, mode string) string {
@@ -911,9 +935,7 @@
 	if a.recorder != nil {
 		a.recorder.Close()
 	}
-	if a.eng != nil {
-		a.eng.Close()
-	}
+	a.replaceEngine(nil)
 	a.wg.Wait()
 	logger.Info("Cleanup complete")
 }
@@ -946,7 +968,5 @@
 
 // SetEngine sets the engine after model download.
 func (a *App) SetEngine(eng engine.Engine) {
-	a.mu.Lock()
-	defer a.mu.Unlock()
-	a.eng = eng
+	a.replaceEngine(eng)
 }

--
Gitblit v1.9.3