| TODO.md | ●●●●● patch | view | raw | blame | history | |
| VoiceSnapGo/app.go | ●●●●● patch | view | raw | blame | history | |
| VoiceSnapGo/build/darwin/Info.plist | ●●●●● patch | view | raw | blame | history | |
| VoiceSnapGo/internal/audio/recorder.go | ●●●●● patch | view | raw | blame | history |
TODO.md
@@ -17,6 +17,15 @@ ## Done - [2026-05-18] 修复停止录音时 `ma_device_stop` 与音频回调互等导致 App 假死的问题。 - 根因: `Recorder.StopAndGetSamples()` 持有录音互斥锁调用 `device.Stop()`;底层 `ma_device_stop` 等待音频回调结束,而音频回调同时等待同一把锁,形成互等。 - 修复: 停止录音时先在锁内摘除设备并标记非录音,释放锁后再调用 `Stop/Uninit`,避免底层停止设备时阻塞音频回调。 - 增加停止设备过程日志: `Stopping audio device`、`Audio device stopped`、`Audio device uninitialized`。 - build: `20260518.0125` - 输出: `VoiceSnapGo/build/local/arm64/VoiceSnap.app` - 输出: `VoiceSnapGo/build/local/arm64/VoiceSnap-2.1.1-build20260518.0125-arm64-local.dmg` - 兼容输出: `VoiceSnapGo/build/local/arm64/VoiceSnap-2.1.1-arm64-local.dmg` 已替换为同一份新包。 - 已安装到 `/Applications/VoiceSnap.app`,并在日志中验证一次完整停止链路。 - [2026-05-17] 放大菜单栏图标的有效绘制区域,改善深色菜单栏里图标过小的问题。 - `VoiceSnapGo/build/darwin/tray_icon.png` 的有效内容区域从约 `156x156` 放大到约 `220x220`。 - build: `20260517.2306` VoiceSnapGo/app.go
@@ -27,7 +27,7 @@ const ( appVersion = "2.1.1" appBuild = "20260517.2306" appBuild = "20260518.0125" appDisplayVersion = appVersion + " (build " + appBuild + ")" appName = "VoiceSnap" VoiceSnapGo/build/darwin/Info.plist
@@ -17,7 +17,7 @@ <key>CFBundleShortVersionString</key> <string>2.1.1</string> <key>CFBundleVersion</key> <string>20260517.2306</string> <string>20260518.0125</string> <key>LSMinimumSystemVersion</key> <string>11.0</string> <key>NSMicrophoneUsageDescription</key> VoiceSnapGo/internal/audio/recorder.go
@@ -151,19 +151,21 @@ // Stop stops recording and discards audio data. func (r *Recorder) Stop() { device := r.detachDevice() stopAndUninitDevice(device) r.mu.Lock() defer r.mu.Unlock() r.stopDevice() r.pcmBuf = nil } // StopAndGetSamples stops recording and returns the captured audio as float32 samples. func (r *Recorder) StopAndGetSamples() []float32 { device := r.detachDevice() stopAndUninitDevice(device) r.mu.Lock() defer r.mu.Unlock() r.stopDevice() if len(r.pcmBuf) < 2 { return nil @@ -203,23 +205,36 @@ // Close releases all audio resources. func (r *Recorder) Close() { device := r.detachDevice() stopAndUninitDevice(device) r.mu.Lock() defer r.mu.Unlock() r.stopDevice() if r.ctx != nil { r.ctx.Free() r.ctx = nil } } func (r *Recorder) stopDevice() { if r.device != nil { r.device.Stop() r.device.Uninit() func (r *Recorder) detachDevice() *malgo.Device { r.mu.Lock() defer r.mu.Unlock() device := r.device r.device = nil } r.isRecording = false return device } func stopAndUninitDevice(device *malgo.Device) { if device == nil { return } logger.Info("Stopping audio device") device.Stop() logger.Info("Audio device stopped") device.Uninit() logger.Info("Audio device uninitialized") } func (r *Recorder) onData(input []byte) {