diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index 8552475..c4ec8be 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -6773,6 +6773,13 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged xiegu: t('cat.optXiegu'), } as Record)[catCfg.backend] ?? ''; + // The radio-over-network entry, which ListAudioInputDevices and + // ListAudioOutputDevices add when the CAT link can carry audio. It is a + // real choice for two of the four fields and nonsense for the other two. + const NET_DEVICE = 'net:radio'; + const soundCardsOnly = (devs: AudioDev[]) => devs.filter((d) => d.id !== NET_DEVICE); + const fromRadioIsNetwork = audioCfg.from_radio === NET_DEVICE; + const deviceSelect = ( field: keyof AudioSettings, devices: AudioDev[], @@ -6807,10 +6814,16 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged {deviceSelect('from_radio', audioInputs, t('aud.phFromRadio'))} {deviceSelect('to_radio', audioOutputs, t('aud.phToRadio'))} + {/* The radio is offered for the two fields it can BE — where the + received audio comes from, and where the voice keyer sends + its messages — and taken out of the other two. It is not a + microphone: choosing it here would record the station you are + listening to instead of your own voice. And it is not a pair of + speakers: the audio going that way is transmit audio. */} - {deviceSelect('recording_device', audioInputs, t('aud.phRecMic'))} + {deviceSelect('recording_device', soundCardsOnly(audioInputs), t('aud.phRecMic'))} - {deviceSelect('listening_device', audioOutputs, t('aud.phListening'))} + {deviceSelect('listening_device', soundCardsOnly(audioOutputs), t('aud.phListening'))}

{t('aud.fromRadioShort')} {t('aud.explainFrom')}{' '} @@ -6828,8 +6841,8 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged size="sm" className="h-8" onClick={toggleMonitor} - disabled={!monitorOn && !audioCfg.from_radio} - title={t('aud.monitorTitle')} + disabled={!monitorOn && (!audioCfg.from_radio || fromRadioIsNetwork)} + title={fromRadioIsNetwork ? t('aud.monitorNoTci') : t('aud.monitorTitle')} > {monitorOn ? t('aud.stopListening') : t('aud.listenRadio')} diff --git a/frontend/src/lib/i18n.tsx b/frontend/src/lib/i18n.tsx index 5e973ab..9195684 100644 --- a/frontend/src/lib/i18n.tsx +++ b/frontend/src/lib/i18n.tsx @@ -494,7 +494,7 @@ const en: Dict = { 'aud.noneDefault': '— none / system default —', 'aud.defaultTag': '(default)', 'aud.fromRadioShort': 'From Radio', 'aud.toRadioShort': 'To Radio', 'aud.explainFrom': '= what you receive (used by the QSO recorder).', 'aud.explainTo': '= where voice-keyer messages are transmitted.', 'aud.monitorTitle': "Hear the rig's RX audio (From Radio) through your Listening device", 'aud.listenRadio': '▶ Listen to radio', 'aud.stopListening': '■ Stop listening', - 'aud.monitorOn': 'RX monitor running — From Radio → Listening device.', 'aud.monitorHint': 'Live-monitor the rig here (USB codec now; network audio later).', + 'aud.monitorOn': 'RX monitor running — From Radio → Listening device.', 'aud.monitorNoTci': 'Listening here is not available with the radio as the source: the TCI stream feeds the QSO recorder, not the monitor. Listen on the radio itself.', 'aud.monitorHint': 'Live-monitor the rig here (USB codec now; network audio later).', 'aud.txTitle': 'Key PTT and pipe your live mic into the rig (To Radio device)', 'aud.talkRadio': '🎙 Talk to radio (TX)', 'aud.stopTalk': '■ Stop talking (TX)', 'aud.txOn': 'TRANSMITTING — mic → To Radio, PTT keyed. Click to stop.', 'aud.txHint': 'Live mic → rig with PTT (USB now; network TX later).', 'aud.recorder': 'QSO recorder', 'aud.recordEvery': 'Record every QSO to an audio file (From Radio + your mic)', 'aud.recFolder': 'Recordings folder', 'aud.browse': 'Browse…', @@ -962,7 +962,7 @@ const fr: Dict = { 'aud.noneDefault': '— aucun / défaut système —', 'aud.defaultTag': '(défaut)', 'aud.fromRadioShort': 'Depuis la radio', 'aud.toRadioShort': 'Vers la radio', 'aud.explainFrom': "= ce que vous recevez (utilisé par l'enregistreur de QSO).", 'aud.explainTo': '= où sont émis les messages du manipulateur vocal.', 'aud.monitorTitle': "Écouter l'audio RX du poste (Depuis la radio) sur votre périphérique d'écoute", 'aud.listenRadio': '▶ Écouter la radio', 'aud.stopListening': "■ Arrêter l'écoute", - 'aud.monitorOn': "Écoute RX active — Depuis la radio → périphérique d'écoute.", 'aud.monitorHint': "Écoute directe du poste (codec USB pour l'instant ; audio réseau plus tard).", + 'aud.monitorOn': "Écoute RX active — Depuis la radio → périphérique d'écoute.", 'aud.monitorNoTci': "L'écoute ici n'est pas disponible avec la radio comme source : le flux TCI alimente l'enregistreur de QSO, pas l'écoute. Écoute sur la radio elle-même.", 'aud.monitorHint': "Écoute directe du poste (codec USB pour l'instant ; audio réseau plus tard).", 'aud.txTitle': 'Activer le PTT et envoyer votre micro vers le poste (périphérique « Vers la radio »)', 'aud.talkRadio': '🎙 Parler à la radio (TX)', 'aud.stopTalk': '■ Arrêter de parler (TX)', 'aud.txOn': 'ÉMISSION — micro → Vers la radio, PTT activé. Cliquez pour arrêter.', 'aud.txHint': "Micro direct → poste avec PTT (USB pour l'instant ; TX réseau plus tard).", 'aud.recorder': 'Enregistreur de QSO', 'aud.recordEvery': 'Enregistrer chaque QSO dans un fichier audio (Depuis la radio + votre micro)', 'aud.recFolder': 'Dossier des enregistrements', 'aud.browse': 'Parcourir…',