fix: say why playing a recording on the air did nothing
"I click play and nothing happens" is what an operator sees when a function returns an error into a promise the interface swallows. Every refusal in the playback path is now logged as well as returned, and each names its own cause — audio not initialised, the take still running, the take empty, the device rejecting the file. One of those was not even checked: playing back needs an OUTPUT device INTO the radio, which is a different setting from the recorder's input and is very likely unset on a station that has only ever recorded. It now refuses with that sentence instead of failing somewhere inside the player.
This commit is contained in:
@@ -7710,16 +7710,32 @@ func (a *App) QSOAudioResume() bool {
|
|||||||
// loop. Stopping is the operator's statement that the take is finished, and it
|
// loop. Stopping is the operator's statement that the take is finished, and it
|
||||||
// is one click they have already made.
|
// is one click they have already made.
|
||||||
func (a *App) QSOAudioPlayOnAir() error {
|
func (a *App) QSOAudioPlayOnAir() error {
|
||||||
|
// Every refusal below is LOGGED as well as returned. "I click play and
|
||||||
|
// nothing happens" is what an operator sees when a function returns an error
|
||||||
|
// into a promise the interface swallowed — and the difference between "no
|
||||||
|
// output device configured" and "the take was empty" cannot be guessed from
|
||||||
|
// the outside.
|
||||||
if a.qsoRec == nil || a.audioMgr == nil {
|
if a.qsoRec == nil || a.audioMgr == nil {
|
||||||
|
applog.Printf("qso-rec: play refused — audio subsystem not initialised")
|
||||||
return fmt.Errorf("audio not initialized")
|
return fmt.Errorf("audio not initialized")
|
||||||
}
|
}
|
||||||
if !a.qsoRec.Paused() {
|
if !a.qsoRec.Paused() {
|
||||||
|
applog.Printf("qso-rec: play refused — the recording is still running (stop it first)")
|
||||||
return fmt.Errorf("stop the recording before playing it on the air")
|
return fmt.Errorf("stop the recording before playing it on the air")
|
||||||
}
|
}
|
||||||
pcm, err := a.qsoRec.PeekQSO()
|
pcm, err := a.qsoRec.PeekQSO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
applog.Printf("qso-rec: play refused — %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
cfgEarly, _ := a.GetAudioSettings()
|
||||||
|
if strings.TrimSpace(cfgEarly.ToRadio) == "" {
|
||||||
|
// The recorder needs an INPUT from the radio; playing back needs an
|
||||||
|
// OUTPUT into it, which is a different device and may well be unset on a
|
||||||
|
// station that only ever recorded.
|
||||||
|
applog.Printf("qso-rec: play refused — no output device to the radio configured (Settings → Audio)")
|
||||||
|
return fmt.Errorf("no audio output to the radio is configured — set it in Settings → Audio")
|
||||||
|
}
|
||||||
// A plain WAV in the data dir, overwritten each time: the player takes a
|
// A plain WAV in the data dir, overwritten each time: the player takes a
|
||||||
// path, and MP3 encoding would add seconds to something the operator is
|
// path, and MP3 encoding would add seconds to something the operator is
|
||||||
// waiting on with the transmitter keyed.
|
// waiting on with the transmitter keyed.
|
||||||
@@ -7728,7 +7744,7 @@ func (a *App) QSOAudioPlayOnAir() error {
|
|||||||
return fmt.Errorf("prepare playback: %w", err)
|
return fmt.Errorf("prepare playback: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, _ := a.GetAudioSettings()
|
cfg := cfgEarly
|
||||||
if err := a.pttKey(cfg); err != nil {
|
if err := a.pttKey(cfg); err != nil {
|
||||||
applog.Printf("qso-rec: PTT on failed before playback: %v", err)
|
applog.Printf("qso-rec: PTT on failed before playback: %v", err)
|
||||||
// Keep going — the audio still reaches the rig and the operator may use VOX.
|
// Keep going — the audio still reaches the rig and the operator may use VOX.
|
||||||
@@ -7738,6 +7754,7 @@ func (a *App) QSOAudioPlayOnAir() error {
|
|||||||
a.pttMu.Unlock()
|
a.pttMu.Unlock()
|
||||||
}
|
}
|
||||||
if err := a.audioMgr.Play(cfg.ToRadio, path, cfg.TXGain); err != nil {
|
if err := a.audioMgr.Play(cfg.ToRadio, path, cfg.TXGain); err != nil {
|
||||||
|
applog.Printf("qso-rec: playback on %q failed: %v", cfg.ToRadio, err)
|
||||||
a.pttMu.Lock()
|
a.pttMu.Lock()
|
||||||
keyed := a.dvkPttKeyed
|
keyed := a.dvkPttKeyed
|
||||||
gen := a.pttGen
|
gen := a.pttGen
|
||||||
|
|||||||
+4
-2
@@ -4,11 +4,13 @@
|
|||||||
"date": "",
|
"date": "",
|
||||||
"en": [
|
"en": [
|
||||||
"FlexRadio: in split, OpsLog stays on the receive slice instead of following the transmitter.",
|
"FlexRadio: in split, OpsLog stays on the receive slice instead of following the transmitter.",
|
||||||
"QSO recording works on CW again. Your own sidetone is not in the file, the other station is."
|
"QSO recording works on CW again. Your own sidetone is not in the file, the other station is.",
|
||||||
|
"Playing a recording on the air now says why when it cannot — most often no audio output to the radio is configured."
|
||||||
],
|
],
|
||||||
"fr": [
|
"fr": [
|
||||||
"FlexRadio : en split, OpsLog reste sur la slice de réception au lieu de suivre l'émission.",
|
"FlexRadio : en split, OpsLog reste sur la slice de réception au lieu de suivre l'émission.",
|
||||||
"L'enregistrement des QSO fonctionne à nouveau en CW. Votre propre signal d'écoute n'est pas dans le fichier, celui du correspondant l'est."
|
"L'enregistrement des QSO fonctionne à nouveau en CW. Votre propre signal d'écoute n'est pas dans le fichier, celui du correspondant l'est.",
|
||||||
|
"L'émission d'un enregistrement indique désormais pourquoi elle échoue — le plus souvent aucune sortie audio vers la radio n'est configurée."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user