83 lines
2.0 KiB
Go
83 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"hamlog/internal/applog"
|
|
"hamlog/internal/audio"
|
|
"hamlog/internal/cwdecode"
|
|
|
|
wruntime "github.com/wailsapp/wails/v2/pkg/runtime"
|
|
)
|
|
|
|
// CW decoder: taps the RX audio device (the same "From radio" capture the DVK
|
|
// and QSO recorder use) and streams decoded Morse text to the UI. It is started
|
|
// only by the frontend, and only while the entry mode is CW.
|
|
|
|
// StartCWDecoder begins decoding CW from the configured RX audio device. The
|
|
// frontend calls this when the decoder toggle is on AND the mode is CW. Safe to
|
|
// call repeatedly; a second call is a no-op while already running.
|
|
func (a *App) StartCWDecoder() error {
|
|
a.cwMu.Lock()
|
|
defer a.cwMu.Unlock()
|
|
if a.cwStop != nil {
|
|
return nil // already running
|
|
}
|
|
dev := ""
|
|
if a.settings != nil {
|
|
dev, _ = a.settings.Get(a.ctx, keyAudioFromRadio)
|
|
}
|
|
if dev == "" {
|
|
return fmt.Errorf("no RX audio device configured (set \"From radio\" in Audio settings)")
|
|
}
|
|
|
|
dec := cwdecode.New(audio.SampleRate,
|
|
func(text string) {
|
|
if a.ctx != nil {
|
|
wruntime.EventsEmit(a.ctx, "cw:text", text)
|
|
}
|
|
},
|
|
func(st cwdecode.Status) {
|
|
if a.ctx != nil {
|
|
wruntime.EventsEmit(a.ctx, "cw:status", st)
|
|
}
|
|
},
|
|
)
|
|
|
|
stop := make(chan struct{})
|
|
a.cwStop = stop
|
|
go func() {
|
|
if err := audio.StreamCapture(dev, stop, dec.Process); err != nil {
|
|
applog.Printf("cw: capture failed: %v", err)
|
|
if a.ctx != nil {
|
|
wruntime.EventsEmit(a.ctx, "cw:error", err.Error())
|
|
}
|
|
}
|
|
// Capture ended (stopped or errored) — clear state so a restart works.
|
|
a.cwMu.Lock()
|
|
if a.cwStop == stop {
|
|
a.cwStop = nil
|
|
}
|
|
a.cwMu.Unlock()
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// StopCWDecoder halts the CW decoder if running.
|
|
func (a *App) StopCWDecoder() {
|
|
a.cwMu.Lock()
|
|
stop := a.cwStop
|
|
a.cwStop = nil
|
|
a.cwMu.Unlock()
|
|
if stop != nil {
|
|
close(stop)
|
|
}
|
|
}
|
|
|
|
// CWDecoderRunning reports whether the decoder is currently capturing.
|
|
func (a *App) CWDecoderRunning() bool {
|
|
a.cwMu.Lock()
|
|
defer a.cwMu.Unlock()
|
|
return a.cwStop != nil
|
|
}
|