feat: added full support in USB (local) & ethernet (local or remote) of audio for Icom
This commit is contained in:
@@ -21,6 +21,8 @@ import {
|
||||
GetEmailSettings, SaveEmailSettings, TestEmail,
|
||||
QSLGetEmailTemplates, QSLSaveEmailTemplates,
|
||||
GetDVKMessages, SetDVKLabel, DVKStartRecord, DVKStopRecord, DVKPreview, DVKStop, GetDVKStatus,
|
||||
AudioStartMonitor, AudioStopMonitor, AudioMonitorActive,
|
||||
AudioStartTX, AudioStopTX, AudioTXActive,
|
||||
ListClusterServers, SaveClusterServer, DeleteClusterServer,
|
||||
GetClusterAutoConnect, SetClusterAutoConnect,
|
||||
ConnectClusterServer, DisconnectClusterServer,
|
||||
@@ -796,7 +798,7 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
const [modeDraft, setModeDraft] = useState('');
|
||||
const [catCfg, setCatCfg] = useState<CATSettings>({
|
||||
enabled: false, backend: 'omnirig', omnirig_rig: 1, flex_host: '', flex_port: 4992, flex_spots: false,
|
||||
icom_port: '', icom_baud: 115200, icom_addr: 0x98, icom_net_host: '', icom_net_user: '', icom_net_pass: '',
|
||||
icom_port: '', icom_baud: 115200, icom_addr: 0x98, icom_net_host: '', icom_net_user: '', icom_net_pass: '', icom_net_audio: false,
|
||||
tci_host: '', tci_port: 40001, tci_spots: false, poll_ms: 250, delay_ms: 0,
|
||||
digital_default: 'FT8',
|
||||
});
|
||||
@@ -863,6 +865,24 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
const [dvkMsgs, setDvkMsgs] = useState<DVKMsg[]>([]);
|
||||
const [dvkStat, setDvkStat] = useState<DVKStat>({ recording: false, playing: false, rec_slot: 0 });
|
||||
const [dvkErr, setDvkErr] = useState('');
|
||||
const [monitorOn, setMonitorOn] = useState(false);
|
||||
const [txOn, setTxOn] = useState(false);
|
||||
useEffect(() => {
|
||||
AudioMonitorActive().then(setMonitorOn).catch(() => {});
|
||||
AudioTXActive().then(setTxOn).catch(() => {});
|
||||
}, []);
|
||||
const toggleMonitor = async () => {
|
||||
try {
|
||||
if (monitorOn) { await AudioStopMonitor(); setMonitorOn(false); }
|
||||
else { await AudioStartMonitor(); setMonitorOn(true); }
|
||||
} catch (err: any) { setDvkErr(String(err?.message ?? err)); }
|
||||
};
|
||||
const toggleTX = async () => {
|
||||
try {
|
||||
if (txOn) { await AudioStopTX(); setTxOn(false); }
|
||||
else { await AudioStartTX(); setTxOn(true); }
|
||||
} catch (err: any) { setDvkErr(String(err?.message ?? err)); }
|
||||
};
|
||||
|
||||
// General behaviour prefs (mirrored to the DB so they travel with data/).
|
||||
const [autofocusWB, setAutofocusWB] = useState(() => localStorage.getItem('opslog.autofocusWB') !== '0');
|
||||
@@ -2065,6 +2085,14 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
onChange={(e) => setCatCfg((s) => ({ ...s, icom_net_pass: e.target.value }))} />
|
||||
</div>
|
||||
<p className="col-span-2 text-xs text-muted-foreground">{t('cat.icomNetHint')}</p>
|
||||
<label className="col-span-2 flex items-start gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={!!(catCfg as any).icom_net_audio}
|
||||
onCheckedChange={(c) => setCatCfg((s) => ({ ...s, icom_net_audio: !!c } as any))} />
|
||||
<span>
|
||||
{t('cat.icomNetAudio')}
|
||||
<span className="block text-[11px] text-muted-foreground">{t('cat.icomNetAudioHint')}</span>
|
||||
</span>
|
||||
</label>
|
||||
</>
|
||||
)}
|
||||
{catCfg.backend === 'tci' && (
|
||||
@@ -3747,6 +3775,40 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
<strong>From Radio</strong> = what you receive (used by the QSO recorder).{' '}
|
||||
<strong>To Radio</strong> = where voice-keyer messages are transmitted.
|
||||
</p>
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
variant={monitorOn ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className="h-8"
|
||||
onClick={toggleMonitor}
|
||||
disabled={!monitorOn && !audioCfg.from_radio}
|
||||
title="Hear the rig's RX audio (From Radio) through your Listening device"
|
||||
>
|
||||
{monitorOn ? '■ Stop listening' : '▶ Listen to radio'}
|
||||
</Button>
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
{monitorOn
|
||||
? 'RX monitor running — From Radio → Listening device.'
|
||||
: 'Live-monitor the rig here (USB codec now; network audio later).'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
variant={txOn ? 'destructive' : 'outline'}
|
||||
size="sm"
|
||||
className="h-8"
|
||||
onClick={toggleTX}
|
||||
disabled={!txOn && !audioCfg.to_radio}
|
||||
title="Key PTT and pipe your live mic into the rig (To Radio device)"
|
||||
>
|
||||
{txOn ? '■ Stop talking (TX)' : '🎙 Talk to radio (TX)'}
|
||||
</Button>
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
{txOn
|
||||
? 'TRANSMITTING — mic → To Radio, PTT keyed. Click to stop.'
|
||||
: 'Live mic → rig with PTT (USB now; network TX later).'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border/60 pt-3 space-y-3 max-w-2xl">
|
||||
|
||||
@@ -134,6 +134,8 @@ const en: Dict = {
|
||||
'cat.enable': 'Enable CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (any rig, Windows COM)', 'cat.optFlex': 'FlexRadio / SmartSDR (native)', 'cat.optIcom': 'Icom CI-V (USB serial)', 'cat.optIcomNet': 'Icom CI-V (network / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.icomNetHost': 'Rig IP / hostname', 'cat.icomNetUser': 'Network user (ID)', 'cat.icomNetPass': 'Network password',
|
||||
'cat.icomNetHint': "Connects to the rig's built-in LAN server directly — no RS-BA1 or Remote Utility needed (close them first). Use the Network User1 ID/Password set in the rig's Network menu. A rig in standby is powered on automatically.",
|
||||
'cat.icomNetAudio': 'Stream RX audio over the network (experimental)',
|
||||
'cat.icomNetAudioHint': 'Play the rig’s received audio through your Listening device (Settings → Audio) over the 50003 stream. Experimental — the audio framing is pending on-rig verification; leave off if control misbehaves.',
|
||||
'cat.omnirigRig': 'OmniRig rig slot', 'cat.flexIp': 'FlexRadio IP', 'cat.port': 'Port', 'cat.flexSpots': 'Show cluster spots on the panadapter', 'cat.flexSpotsHint': "(spots from OpsLog's DX cluster appear on the radio, auto-expire after 30 min)",
|
||||
'cat.icomPort': 'Icom CI-V port', 'cat.selectCom': 'Select COM port', 'cat.noPorts': 'No ports found', 'cat.baud': 'Baud rate', 'cat.civAddr': 'CI-V address (hex)', 'cat.civHint': 'IC-7610 = 98, IC-7300 = 94, IC-9700 = A2, IC-705 = A4. Set "CI-V USB Echo Back" OFF and CI-V baud to match on the rig.',
|
||||
'cat.tciHost': 'TCI host', 'cat.tciHint': 'Enable the TCI server in ExpertSDR2/EESDR (Options → TCI). Default port 40001. Use 127.0.0.1 when OpsLog runs on the same PC.', 'cat.tciSpots': 'Show cluster spots on the panorama', 'cat.tciSpotsHint': "(spots from OpsLog's DX cluster appear on the SDR panadapter)",
|
||||
@@ -327,6 +329,8 @@ const fr: Dict = {
|
||||
'cat.enable': 'Activer le CAT', 'cat.backend': 'Backend', 'cat.optOmnirig': 'OmniRig (tout poste, COM Windows)', 'cat.optFlex': 'FlexRadio / SmartSDR (natif)', 'cat.optIcom': 'Icom CI-V (USB série)', 'cat.optIcomNet': 'Icom CI-V (réseau / remote)', 'cat.optTci': 'TCI (Expert Electronics / SunSDR)',
|
||||
'cat.icomNetHost': 'IP / nom d\'hôte du poste', 'cat.icomNetUser': 'Utilisateur réseau (ID)', 'cat.icomNetPass': 'Mot de passe réseau',
|
||||
'cat.icomNetHint': "Se connecte directement au serveur LAN intégré du poste — sans RS-BA1 ni Remote Utility (ferme-les d'abord). Utilise l'ID/mot de passe Network User1 configurés dans le menu Network du poste. Un poste en veille est allumé automatiquement.",
|
||||
'cat.icomNetAudio': 'Diffuser l’audio RX par le réseau (expérimental)',
|
||||
'cat.icomNetAudioHint': 'Écoute l’audio reçu du poste sur ton périphérique d’écoute (Réglages → Audio) via le flux 50003. Expérimental — le format audio reste à vérifier sur le poste ; laisse désactivé si le contrôle se comporte mal.',
|
||||
'cat.omnirigRig': 'Slot OmniRig', 'cat.flexIp': 'IP FlexRadio', 'cat.port': 'Port', 'cat.flexSpots': 'Afficher les spots cluster sur le panadapter', 'cat.flexSpotsHint': "(les spots du cluster DX d'OpsLog apparaissent sur la radio, expirent après 30 min)",
|
||||
'cat.icomPort': 'Port CI-V Icom', 'cat.selectCom': 'Choisir un port COM', 'cat.noPorts': 'Aucun port trouvé', 'cat.baud': 'Débit (baud)', 'cat.civAddr': 'Adresse CI-V (hex)', 'cat.civHint': 'IC-7610 = 98, IC-7300 = 94, IC-9700 = A2, IC-705 = A4. Mets « CI-V USB Echo Back » sur OFF et fais correspondre le débit CI-V sur le poste.',
|
||||
'cat.tciHost': 'Hôte TCI', 'cat.tciHint': 'Active le serveur TCI dans ExpertSDR2/EESDR (Options → TCI). Port par défaut 40001. Utilise 127.0.0.1 si OpsLog tourne sur le même PC.', 'cat.tciSpots': 'Afficher les spots cluster sur le panorama', 'cat.tciSpotsHint': "(les spots du cluster DX d'OpsLog apparaissent sur le panadapter SDR)",
|
||||
|
||||
Vendored
+12
@@ -36,6 +36,18 @@ export function ApplyAwardPreset(arg1:string,arg2:string):Promise<number>;
|
||||
|
||||
export function AssignAwardRefToQSOs(arg1:string,arg2:string,arg3:Array<number>):Promise<number>;
|
||||
|
||||
export function AudioMonitorActive():Promise<boolean>;
|
||||
|
||||
export function AudioStartMonitor():Promise<void>;
|
||||
|
||||
export function AudioStartTX():Promise<void>;
|
||||
|
||||
export function AudioStopMonitor():Promise<void>;
|
||||
|
||||
export function AudioStopTX():Promise<void>;
|
||||
|
||||
export function AudioTXActive():Promise<boolean>;
|
||||
|
||||
export function AwardCellQSOs(arg1:string,arg2:string,arg3:string):Promise<Array<qso.QSO>>;
|
||||
|
||||
export function AwardFields():Promise<Array<string>>;
|
||||
|
||||
@@ -34,6 +34,30 @@ export function AssignAwardRefToQSOs(arg1, arg2, arg3) {
|
||||
return window['go']['main']['App']['AssignAwardRefToQSOs'](arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
export function AudioMonitorActive() {
|
||||
return window['go']['main']['App']['AudioMonitorActive']();
|
||||
}
|
||||
|
||||
export function AudioStartMonitor() {
|
||||
return window['go']['main']['App']['AudioStartMonitor']();
|
||||
}
|
||||
|
||||
export function AudioStartTX() {
|
||||
return window['go']['main']['App']['AudioStartTX']();
|
||||
}
|
||||
|
||||
export function AudioStopMonitor() {
|
||||
return window['go']['main']['App']['AudioStopMonitor']();
|
||||
}
|
||||
|
||||
export function AudioStopTX() {
|
||||
return window['go']['main']['App']['AudioStopTX']();
|
||||
}
|
||||
|
||||
export function AudioTXActive() {
|
||||
return window['go']['main']['App']['AudioTXActive']();
|
||||
}
|
||||
|
||||
export function AwardCellQSOs(arg1, arg2, arg3) {
|
||||
return window['go']['main']['App']['AwardCellQSOs'](arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
@@ -1349,6 +1349,7 @@ export namespace main {
|
||||
icom_net_host: string;
|
||||
icom_net_user: string;
|
||||
icom_net_pass: string;
|
||||
icom_net_audio: boolean;
|
||||
tci_host: string;
|
||||
tci_port: number;
|
||||
tci_spots: boolean;
|
||||
@@ -1374,6 +1375,7 @@ export namespace main {
|
||||
this.icom_net_host = source["icom_net_host"];
|
||||
this.icom_net_user = source["icom_net_user"];
|
||||
this.icom_net_pass = source["icom_net_pass"];
|
||||
this.icom_net_audio = source["icom_net_audio"];
|
||||
this.tci_host = source["tci_host"];
|
||||
this.tci_port = source["tci_port"];
|
||||
this.tci_spots = source["tci_spots"];
|
||||
|
||||
Reference in New Issue
Block a user