fix(icom): create the audio manager before the CAT link comes up
reloadCAT builds the network audio sink gated on audioMgr, and startup created the manager AFTER the first reloadCAT: every fresh launch connected with audio silently off however the option was set, and the operator had to untick/save/retick it to hear anything. The manager is idle-until-used, so creating it earlier costs nothing.
This commit is contained in:
@@ -1252,6 +1252,49 @@ func (a *App) startup(ctx context.Context) {
|
||||
go a.applyRelayAuto(s.FreqHz, s.Band)
|
||||
}
|
||||
})
|
||||
// Digital Voice Keyer + QSO recorder (WASAPI). Idle until used. Created
|
||||
// BEFORE the CAT link comes up, and it matters: a network Icom with RX
|
||||
// audio enabled builds its audio sink inside reloadCAT, gated on audioMgr —
|
||||
// when the manager was created later, every fresh launch connected with
|
||||
// audio silently off, and the operator had to untick/save/retick the option
|
||||
// to hear anything.
|
||||
a.audioMgr = audio.NewManager(func() {
|
||||
st := a.dvkStatus()
|
||||
// When a voice message finishes (or is stopped), drop the PTT we keyed
|
||||
// for it — but tag the release with the current key generation so it
|
||||
// can't cut a transmission a newer message already started.
|
||||
if !st.Playing {
|
||||
a.pttMu.Lock()
|
||||
keyed := a.dvkPttKeyed
|
||||
gen := a.pttGen
|
||||
if keyed {
|
||||
a.dvkPttKeyed = false
|
||||
}
|
||||
a.pttMu.Unlock()
|
||||
if keyed {
|
||||
go a.dvkUnkeyPTT(gen)
|
||||
}
|
||||
// And give the microphone back, if we took it (see raiseFlexDVKDax).
|
||||
// Off the callback's goroutine: this talks to the radio, and the
|
||||
// audio manager is reporting a state change, not waiting on us.
|
||||
go a.lowerFlexDVKDax()
|
||||
}
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "audio:status", st)
|
||||
}
|
||||
})
|
||||
a.qsoRec = audio.NewRecorder()
|
||||
if a.audioMgr != nil {
|
||||
// A running monitor picks the new level up immediately: the operator is
|
||||
// listening while they move the slider, and asking them to stop and
|
||||
// restart it to hear the change is how a working control gets reported
|
||||
// as broken.
|
||||
if cfg, err := a.GetAudioSettings(); err == nil {
|
||||
a.audioMgr.SetMonitorGain(cfg.FromGain)
|
||||
}
|
||||
}
|
||||
a.startQSORecorderIfEnabled()
|
||||
|
||||
a.reloadCAT()
|
||||
|
||||
// The QSO logbook lives where the ACTIVE PROFILE points it: the local SQLite
|
||||
@@ -1479,44 +1522,6 @@ func (a *App) startup(ctx context.Context) {
|
||||
})
|
||||
a.solar.Start()
|
||||
|
||||
// Digital Voice Keyer + QSO recorder (WASAPI). Idle until used.
|
||||
a.audioMgr = audio.NewManager(func() {
|
||||
st := a.dvkStatus()
|
||||
// When a voice message finishes (or is stopped), drop the PTT we keyed
|
||||
// for it — but tag the release with the current key generation so it
|
||||
// can't cut a transmission a newer message already started.
|
||||
if !st.Playing {
|
||||
a.pttMu.Lock()
|
||||
keyed := a.dvkPttKeyed
|
||||
gen := a.pttGen
|
||||
if keyed {
|
||||
a.dvkPttKeyed = false
|
||||
}
|
||||
a.pttMu.Unlock()
|
||||
if keyed {
|
||||
go a.dvkUnkeyPTT(gen)
|
||||
}
|
||||
// And give the microphone back, if we took it (see raiseFlexDVKDax).
|
||||
// Off the callback's goroutine: this talks to the radio, and the
|
||||
// audio manager is reporting a state change, not waiting on us.
|
||||
go a.lowerFlexDVKDax()
|
||||
}
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "audio:status", st)
|
||||
}
|
||||
})
|
||||
a.qsoRec = audio.NewRecorder()
|
||||
if a.audioMgr != nil {
|
||||
// A running monitor picks the new level up immediately: the operator is
|
||||
// listening while they move the slider, and asking them to stop and
|
||||
// restart it to hear the change is how a working control gets reported
|
||||
// as broken.
|
||||
if cfg, err := a.GetAudioSettings(); err == nil {
|
||||
a.audioMgr.SetMonitorGain(cfg.FromGain)
|
||||
}
|
||||
}
|
||||
a.startQSORecorderIfEnabled()
|
||||
|
||||
// NET Control store (global JSON, shared across logbooks).
|
||||
if ns, err := netctl.Open(filepath.Join(a.dataDir, "nets.json")); err != nil {
|
||||
applog.Printf("netctl: open failed: %v", err)
|
||||
|
||||
+4
-2
@@ -17,7 +17,8 @@
|
||||
"QSO recorder: starting a fresh manual take resets the counter for good — it used to flash 0 and jump back to the previous take’s elapsed time.",
|
||||
"MY_RIG follows the radio actually connected: the entry form now asks the active radio first, before the per-band default — an IC-7760 on the air no longer logs as the Flex the band plan names.",
|
||||
"QSO recorder: a manual take on a network Icom records the network RX stream, not the “From radio” sound card (which captured another radio’s DAX on a mixed station).",
|
||||
"Icom network audio: duplicate and late-retransmitted packets no longer reach the recorder — recordings came out longer than the QSO, slowed and stuttering, while the speakers played fine."
|
||||
"Icom network audio: duplicate and late-retransmitted packets no longer reach the recorder — recordings came out longer than the QSO, slowed and stuttering, while the speakers played fine.",
|
||||
"Icom network audio: it now starts with the app — launching OpsLog connected with audio silently off, and the option had to be unticked and re-saved to hear anything."
|
||||
],
|
||||
"fr": [
|
||||
"Console Elecraft : le S-mètre est calibré sur un vrai K3 — S9 et les +dB correspondent désormais à l’affichage de la radio (il lisait environ deux points S trop bas).",
|
||||
@@ -34,7 +35,8 @@
|
||||
"Enregistreur de QSO : démarrer une nouvelle prise manuelle remet le compteur à zéro pour de bon — il affichait 0 puis resautait au temps de la prise précédente.",
|
||||
"MY_RIG suit la radio réellement connectée : le formulaire interroge d’abord la radio active, avant le défaut par bande — un IC-7760 à l’antenne ne se logue plus comme le Flex prévu par le plan de bande.",
|
||||
"Enregistreur de QSO : une prise manuelle sur un Icom réseau enregistre le flux RX réseau, pas la carte son « From Radio » (qui capturait le DAX d’une autre radio sur une station mixte).",
|
||||
"Audio réseau Icom : les paquets dupliqués ou retransmis en retard n’atteignent plus l’enregistreur — les enregistrements sortaient plus longs que le QSO, ralentis et hachés, alors que les haut-parleurs jouaient bien."
|
||||
"Audio réseau Icom : les paquets dupliqués ou retransmis en retard n’atteignent plus l’enregistreur — les enregistrements sortaient plus longs que le QSO, ralentis et hachés, alors que les haut-parleurs jouaient bien.",
|
||||
"Audio réseau Icom : il démarre maintenant avec l’application — au lancement, la connexion se faisait audio coupé, et il fallait décocher/recocher l’option pour entendre quelque chose."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user