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)
|
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()
|
a.reloadCAT()
|
||||||
|
|
||||||
// The QSO logbook lives where the ACTIVE PROFILE points it: the local SQLite
|
// 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()
|
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).
|
// NET Control store (global JSON, shared across logbooks).
|
||||||
if ns, err := netctl.Open(filepath.Join(a.dataDir, "nets.json")); err != nil {
|
if ns, err := netctl.Open(filepath.Join(a.dataDir, "nets.json")); err != nil {
|
||||||
applog.Printf("netctl: open failed: %v", err)
|
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.",
|
"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.",
|
"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).",
|
"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": [
|
"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).",
|
"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.",
|
"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.",
|
"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).",
|
"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