fix: check the configured capture device still exists before recording

Third empty recording, same station, and the sequence was as plain as it gets:
type the call, click record, log the QSO. The device opened and never streamed.

Endpoint ids are what gets stored, and a DAX channel that is reconfigured,
disabled or recreated comes back with a DIFFERENT id. The stale one opens
without complaint on some drivers and simply never delivers — indistinguishable
from a quiet band until the file turns out to be empty.

The recorder now checks the id against the current endpoint list when it starts,
which takes milliseconds, and says outright that the configured input is gone —
on screen, not only in the log. If it IS still there, the answer is equally
useful: the device exists and the fault is upstream, in whatever should be
feeding it.
This commit is contained in:
2026-07-31 00:12:51 +02:00
parent a93f52d2b9
commit b25efabab8
+24
View File
@@ -130,6 +130,30 @@ func (r *Recorder) Start(fromDev, micDev string, prerollSec int) error {
if prerollSec < 0 {
prerollSec = 0
}
// Does the configured endpoint still EXIST?
//
// Endpoint ids are stored, and a DAX channel that is reconfigured, disabled
// or removed comes back with a different id. The old one then opens without
// complaint on some drivers and simply never streams — which is
// indistinguishable from a quiet band until the recording turns out empty.
// Checking the list takes milliseconds and answers it outright.
if devs, derr := ListInputDevices(); derr == nil {
known := func(id string) bool {
for _, d := range devs {
if d.ID == id {
return true
}
}
return false
}
if fromDev != "" && !known(fromDev) {
LogSink("recorder: the configured radio input no longer exists (%s) — re-select it in Settings → Audio", fromDev)
AlertSink("The configured radio audio input no longer exists — re-select it in Settings")
}
if micDev != "" && micDev != fromDev && !known(micDev) {
LogSink("recorder: the configured microphone no longer exists (%s) — re-select it in Settings → Audio", micDev)
}
}
r.prerollSamples = prerollSec * sampleRate
r.twoSrc = micDev != "" && micDev != fromDev
r.stopCh = make(chan struct{})