feat(dvk): key the DATA input, not the microphone

From a TS-590SG report: the voice keyer played through the rig's USB
codec and the radio transmitted silence. Its manual says why — 'TX P1,
0: SEND (normal transmission using the MIC input), 1: DATA SEND
(ACC2/USB input)' — and OpsLog only ever sent the bare TX, so the radio
dutifully opened a front microphone nobody was speaking into.

An option on the audio page, shown for CAT keying, says where the
keyer's audio actually arrives; the manager routes it to a backend that
draws the distinction and falls back to the ordinary key for every rig
where one PTT is all there is. Test PTT goes down the same path, so it
tests what will happen rather than something adjacent.
This commit is contained in:
2026-09-02 16:17:50 +02:00
parent b7c87def5b
commit 8685dbd6cf
7 changed files with 83 additions and 13 deletions
+12 -2
View File
@@ -1702,13 +1702,13 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
type AudioSettings = {
from_radio: string; to_radio: string; recording_device: string; listening_device: string;
qso_record: boolean; qso_dir: string; preroll_seconds: number;
ptt_method: 'none' | 'cat' | 'rts' | 'dtr'; ptt_port: string; format: 'wav' | 'mp3';
ptt_method: 'none' | 'cat' | 'rts' | 'dtr'; ptt_port: string; ptt_data?: boolean; format: 'wav' | 'mp3';
from_gain: number; mic_gain: number; tx_gain: number; qso_play_gain: number;
};
type AudioDev = { id: string; name: string; default: boolean };
const [audioCfg, setAudioCfg] = useState<AudioSettings>({
from_radio: '', to_radio: '', recording_device: '', listening_device: '',
qso_record: false, qso_dir: '', preroll_seconds: 8, ptt_method: 'none', ptt_port: '', format: 'wav',
qso_record: false, qso_dir: '', preroll_seconds: 8, ptt_method: 'none', ptt_port: '', ptt_data: false, format: 'wav',
from_gain: 100, mic_gain: 100, tx_gain: 100, qso_play_gain: 100,
});
const [audioInputs, setAudioInputs] = useState<AudioDev[]>([]);
@@ -7251,6 +7251,16 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
</Button>
)}
</div>
{audioCfg.ptt_method === 'cat' && (
<>
<span />
<label className="flex items-start gap-2 text-sm cursor-pointer" title={t('aud.pttDataHint')}>
<Checkbox className="mt-0.5" checked={!!audioCfg.ptt_data}
onCheckedChange={(c) => setAudioField({ ptt_data: !!c })} />
<span>{t('aud.pttData')}</span>
</label>
</>
)}
{(audioCfg.ptt_method === 'rts' || audioCfg.ptt_method === 'dtr') && (
<>
<Label className="text-sm">{t('aud.pttPort')}</Label>
+2 -2
View File
@@ -535,7 +535,7 @@ const en: Dict = {
'aud.preroll': 'Pre-roll (seconds)', 'aud.format': 'File format', 'aud.wav': 'WAV (lossless, larger)', 'aud.mp3': 'MP3 (compressed, small)',
'aud.fromLevel': 'From Radio level', 'aud.txLevel': 'Voice keyer level', 'aud.txLevelHint': 'Level of the recorded messages sent to the radio. Raise it if your voice keyer is much quieter than your microphone; Play previews at this same level. If the radio transmits almost nothing, its modulation source is still the front microphone: on an FTDX10 set MENU → SSB MOD SOURCE to REAR (the USB input).', 'aud.micLevel': 'Mic level', 'aud.qsoPlayLevel': 'QSO playback level', 'aud.levelHint': 'If your voice is louder than the station, lower Mic level.',
'aud.autoSend': 'Auto-send the recording to the station by e-mail when I log a QSO',
'aud.dvkTitle': 'Voice keyer messages (F1F12)', 'aud.deleteMsg': 'Delete this message', 'aud.pttMethod': 'PTT method', 'aud.pttNone': 'None (VOX)', 'aud.pttCat': 'CAT (the radio link)', 'aud.pttRts': 'Serial RTS', 'aud.pttDtr': 'Serial DTR',
'aud.dvkTitle': 'Voice keyer messages (F1F12)', 'aud.deleteMsg': 'Delete this message', 'aud.pttData': 'The keyers audio arrives on the radios DATA / USB input', 'aud.pttDataHint': 'Changes which transmit command is sent: a Kenwood TS-590 takes TX1 (ACC2/USB) instead of TX (front microphone). Without it the radio transmits while listening to a microphone nobody is speaking into. Rigs with a single PTT ignore this.', 'aud.pttMethod': 'PTT method', 'aud.pttNone': 'None (VOX)', 'aud.pttCat': 'CAT (the radio link)', 'aud.pttRts': 'Serial RTS', 'aud.pttDtr': 'Serial DTR',
'aud.testPtt': 'Test PTT', 'aud.pttPort': 'PTT COM port', 'aud.pickPort': 'Pick a COM port', 'aud.selectPort': '— select —', 'aud.refresh': 'Refresh',
'aud.msgPlaceholder': 'Message {n} label (CQ, report, 73…)', 'aud.holdRec': '● Hold to rec', 'aud.recordingNow': '● Recording…', 'aud.play': '▶ Play', 'aud.stop': '■ Stop',
'aud.errPttTest': 'PTT test: ', 'aud.errRecord': 'Record: ', 'aud.errSave': 'Save: ', 'aud.errPlay': 'Play: ',
@@ -1037,7 +1037,7 @@ const fr: Dict = {
'aud.preroll': 'Pré-enregistrement (secondes)', 'aud.format': 'Format de fichier', 'aud.wav': 'WAV (sans perte, plus volumineux)', 'aud.mp3': 'MP3 (compressé, léger)',
'aud.fromLevel': 'Niveau depuis la radio', 'aud.txLevel': 'Niveau du voice keyer', 'aud.txLevelHint': "Niveau des messages enregistrés envoyés à la radio. Augmentez-le si votre voice keyer est bien plus faible que votre micro ; Lire fait entendre ce même niveau. Si la radio n'émet presque rien, c'est que sa source de modulation est restée le micro de façade : sur un FTDX10, réglez MENU → SSB MOD SOURCE sur REAR (l'entrée USB).", 'aud.micLevel': 'Niveau micro', 'aud.qsoPlayLevel': 'Niveau de relecture QSO', 'aud.levelHint': 'Si votre voix est plus forte que la station, baissez le niveau micro.',
'aud.autoSend': "Envoyer automatiquement l'enregistrement à la station par e-mail lorsque j'enregistre un QSO",
'aud.dvkTitle': 'Messages du manipulateur vocal (F1F12)', 'aud.deleteMsg': 'Supprimer ce message', 'aud.pttMethod': 'Méthode PTT', 'aud.pttNone': 'Aucune (VOX)', 'aud.pttCat': 'CAT (la liaison radio)', 'aud.pttRts': 'RTS série', 'aud.pttDtr': 'DTR série',
'aud.dvkTitle': 'Messages du manipulateur vocal (F1F12)', 'aud.deleteMsg': 'Supprimer ce message', 'aud.pttData': 'Laudio du keyer arrive sur lentrée DATA / USB de la radio', 'aud.pttDataHint': 'Change la commande d’émission envoyée : un Kenwood TS-590 attend TX1 (ACC2/USB) au lieu de TX (micro de face avant). Sans cela la radio émet en écoutant un micro devant lequel personne ne parle. Les postes à PTT unique lignorent.', 'aud.pttMethod': 'Méthode PTT', 'aud.pttNone': 'Aucune (VOX)', 'aud.pttCat': 'CAT (la liaison radio)', 'aud.pttRts': 'RTS série', 'aud.pttDtr': 'DTR série',
'aud.testPtt': 'Tester le PTT', 'aud.pttPort': 'Port COM du PTT', 'aud.pickPort': 'Choisir un port COM', 'aud.selectPort': '— choisir —', 'aud.refresh': 'Actualiser',
'aud.msgPlaceholder': 'Libellé du message {n} (CQ, report, 73…)', 'aud.holdRec': '● Maintenir pour enreg.', 'aud.recordingNow': '● Enregistrement…', 'aud.play': '▶ Lire', 'aud.stop': '■ Arrêter',
'aud.errPttTest': 'Test PTT : ', 'aud.errRecord': 'Enregistrement : ', 'aud.errSave': 'Sauvegarde : ', 'aud.errPlay': 'Lecture : ',
+2
View File
@@ -1924,6 +1924,7 @@ export namespace main {
preroll_seconds: number;
ptt_method: string;
ptt_port: string;
ptt_data: boolean;
format: string;
from_gain: number;
mic_gain: number;
@@ -1945,6 +1946,7 @@ export namespace main {
this.preroll_seconds = source["preroll_seconds"];
this.ptt_method = source["ptt_method"];
this.ptt_port = source["ptt_port"];
this.ptt_data = source["ptt_data"];
this.format = source["format"];
this.from_gain = source["from_gain"];
this.mic_gain = source["mic_gain"];