feat(icom): live microphone over the network — the last remote brick
The talk button learns the network road the voice keyer already took: when To-radio is the radio itself, the microphone is captured and re-framed into the rig's 320-sample packets, the capture callback serving as the clock — the mic delivers in real time, so no ring and no pacer. Counters and the frame remainder live on the audio stream, so a talk session spans calls. PTT keys before and releases after, through the same code as the USB path. With this, a network Icom is a complete remote station over three UDP ports: RX audio to the headset, live voice and recorded messages back, CW through the rig's keyer, CAT for everything else.
This commit is contained in:
@@ -356,6 +356,29 @@ func (m *Manager) StartTXAudio(micDev, toRadioDev string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartTXAudioNetwork pipes the live microphone into a SEND function instead
|
||||
// of a render device — the talk button when the radio is reached over its own
|
||||
// link. No ring and no pacing goroutine: the microphone delivers in real time,
|
||||
// and the sender re-frames to the rig's cadence, so the capture callback IS
|
||||
// the clock.
|
||||
func (m *Manager) StartTXAudioNetwork(micDev string, send func([]byte) error) error {
|
||||
m.mu.Lock()
|
||||
if m.txStop != nil {
|
||||
m.mu.Unlock()
|
||||
return fmt.Errorf("TX audio already running")
|
||||
}
|
||||
stop := make(chan struct{})
|
||||
m.txStop = stop
|
||||
m.mu.Unlock()
|
||||
go func() {
|
||||
if err := captureStream(micDev, stop, func(chunk []byte) { _ = send(chunk) }); err != nil {
|
||||
LogSink("audio: network TX capture from %q failed: %v", DeviceName(micDev), err)
|
||||
}
|
||||
}()
|
||||
m.notify()
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopTXAudio stops the TX mic→rig passthrough.
|
||||
func (m *Manager) StopTXAudio() {
|
||||
m.mu.Lock()
|
||||
|
||||
Reference in New Issue
Block a user