package main // The voice keyer, through the radio's own link. // // Selecting the radio as the "To radio" output makes the voice keyer hand its // messages to the CAT backend instead of a sound card. Everything around it is // unchanged — the same PTT before and after, the same gain, the same files — // which is the point: the audio takes a different road, not a different route. import ( "fmt" "hamlog/internal/applog" "hamlog/internal/audio" "hamlog/internal/cat" ) // tciTXPlayer hands one message to the radio. // // The controller is fetched on the CAT goroutine and the message is then played // OFF it. Playing on it would hold that goroutine for the length of the // message, and everything else about the rig — frequency, mode, PTT state — // goes through the same place: a ten-second call would freeze the display and // the antenna following for ten seconds. The TCI backend serialises its own // writes, so this is safe to call from here. func (a *App) tciTXPlayer(pcm []byte, rate, ch, bits int, stop <-chan struct{}) error { if a.cat == nil { return fmt.Errorf("CAT not initialized") } type txPlayer interface { PlayTXAudio(pcm []byte, rate, ch, bits int, stop <-chan struct{}) error } var player txPlayer err := a.cat.TCIAudioDo(func(t cat.TCIAudioController) error { p, ok := t.(txPlayer) if !ok { return fmt.Errorf("this radio cannot take transmit audio over its CAT link") } player = p return nil }) if err != nil { return err } return player.PlayTXAudio(pcm, rate, ch, bits, stop) } // installTCITXPlayer offers the radio as an audio output, or withdraws it. // // Withdrawing matters as much as offering: a radio that has gone away must stop // being a device the voice keyer will happily "play" to, or a message goes // nowhere and the operator hears their own PTT click and assumes it worked. func (a *App) installTCITXPlayer(on bool) { if !on { audio.SetNetworkPlayer(nil) return } audio.SetNetworkPlayer(a.tciTXPlayer) applog.Printf("tci: the radio is available as an audio output — no virtual cable needed for the voice keyer") }