feat: added mute and AGC-T to Flex control
This commit is contained in:
@@ -7406,6 +7406,13 @@ func (a *App) FlexSetAudioLevel(l int) error {
|
||||
return a.cat.FlexDo(func(fc cat.FlexController) error { return fc.SetAudioLevel(l) })
|
||||
}
|
||||
|
||||
func (a *App) FlexSetMute(on bool) error {
|
||||
if a.cat == nil {
|
||||
return fmt.Errorf("cat not initialized")
|
||||
}
|
||||
return a.cat.FlexDo(func(fc cat.FlexController) error { return fc.SetMute(on) })
|
||||
}
|
||||
|
||||
func (a *App) FlexSetNB(on bool) error {
|
||||
if a.cat == nil {
|
||||
return fmt.Errorf("cat not initialized")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Radio, Zap, Power, AudioLines, Flame, Gauge } from 'lucide-react';
|
||||
import { Radio, Zap, Power, AudioLines, Flame, Gauge, Volume2, VolumeX } from 'lucide-react';
|
||||
import {
|
||||
GetFlexState, FlexSetPower, FlexSetTunePower, FlexTune, FlexSetVox, FlexSetVoxLevel, FlexSetVoxDelay,
|
||||
FlexSetProcessor, FlexSetProcessorLevel, FlexSetMon, FlexSetMonLevel, FlexSetMic,
|
||||
FlexMox, FlexAmpOperate,
|
||||
GetPGXLStatus, PGXLSetFanMode,
|
||||
FlexSetAGCMode, FlexSetAGCThreshold, FlexSetAudioLevel,
|
||||
FlexSetAGCMode, FlexSetAGCThreshold, FlexSetAudioLevel, FlexSetMute,
|
||||
FlexSetNB, FlexSetNBLevel, FlexSetNR, FlexSetNRLevel, FlexSetANF, FlexSetANFLevel,
|
||||
FlexSetAPF, FlexSetAPFLevel, FlexSetCWSpeed, FlexSetCWPitch, FlexSetCWBreakInDelay,
|
||||
FlexSetCWSidetone, FlexSetSidetoneLevel, FlexSetCWFilter, FlexSetFilter,
|
||||
@@ -19,7 +19,7 @@ type FlexState = {
|
||||
proc_enable: boolean; proc_level: number;
|
||||
mon: boolean; mon_level: number; mic_level: number;
|
||||
atu_status?: string; atu_memories: boolean;
|
||||
rx_avail: boolean; agc_mode?: string; agc_threshold: number; audio_level: number;
|
||||
rx_avail: boolean; agc_mode?: string; agc_threshold: number; audio_level: number; mute: boolean;
|
||||
nb: boolean; nb_level: number; nr: boolean; nr_level: number; anf: boolean; anf_level: number;
|
||||
mode?: string;
|
||||
cw_speed: number; cw_pitch: number; cw_break_in_delay: number; cw_sidetone: boolean; cw_mon_level: number;
|
||||
@@ -34,7 +34,7 @@ const ZERO: FlexState = {
|
||||
available: false, rf_power: 0, tune_power: 0, tune: false, transmitting: false,
|
||||
vox_enable: false, vox_level: 0, vox_delay: 0, proc_enable: false, proc_level: 0,
|
||||
mon: false, mon_level: 0, mic_level: 0, atu_memories: false,
|
||||
rx_avail: false, agc_threshold: 0, audio_level: 0,
|
||||
rx_avail: false, agc_threshold: 0, audio_level: 0, mute: false,
|
||||
nb: false, nb_level: 0, nr: false, nr_level: 0, anf: false, anf_level: 0,
|
||||
cw_speed: 25, cw_pitch: 600, cw_break_in_delay: 30, cw_sidetone: true, cw_mon_level: 0,
|
||||
apf: false, apf_level: 0, filter_lo: 0, filter_hi: 0,
|
||||
@@ -363,14 +363,21 @@ export function FlexPanel() {
|
||||
onChange={(v) => change('agc_mode', v, () => FlexSetAGCMode(v))} />
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">Thresh</span>
|
||||
<Slider value={st.agc_threshold} disabled={rxOff} accent="#64748b" onChange={(v) => change('agc_threshold', v, () => FlexSetAGCThreshold(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.agc_threshold}</span>
|
||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AF</span>
|
||||
<button type="button" disabled={rxOff}
|
||||
title={st.mute ? 'Muted — click to unmute' : 'Mute RX audio'}
|
||||
onClick={() => change('mute', !st.mute, () => FlexSetMute(!st.mute))}
|
||||
className={cn('shrink-0 rounded p-1 transition-colors disabled:opacity-30',
|
||||
st.mute ? 'bg-red-600 text-white' : 'text-muted-foreground hover:bg-muted')}>
|
||||
{st.mute ? <VolumeX className="size-3.5" /> : <Volume2 className="size-3.5" />}
|
||||
</button>
|
||||
<Slider value={st.audio_level} disabled={rxOff || st.mute} accent="#16a34a" onChange={(v) => change('audio_level', v, () => FlexSetAudioLevel(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.mute ? '—' : st.audio_level}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AF</span>
|
||||
<Slider value={st.audio_level} disabled={rxOff} accent="#16a34a" onChange={(v) => change('audio_level', v, () => FlexSetAudioLevel(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.audio_level}</span>
|
||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AGC-T</span>
|
||||
<Slider value={st.agc_threshold} disabled={rxOff} accent="#64748b" onChange={(v) => change('agc_threshold', v, () => FlexSetAGCThreshold(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.agc_threshold}</span>
|
||||
</div>
|
||||
<div className="border-t border-border/60 pt-3 space-y-3">
|
||||
<LevelRow label="NB" on={st.nb} disabled={rxOff} value={st.nb_level} accent="amber" sliderAccent="#d97706"
|
||||
|
||||
Vendored
+2
@@ -174,6 +174,8 @@ export function FlexSetMon(arg1:boolean):Promise<void>;
|
||||
|
||||
export function FlexSetMonLevel(arg1:number):Promise<void>;
|
||||
|
||||
export function FlexSetMute(arg1:boolean):Promise<void>;
|
||||
|
||||
export function FlexSetNB(arg1:boolean):Promise<void>;
|
||||
|
||||
export function FlexSetNBLevel(arg1:number):Promise<void>;
|
||||
|
||||
@@ -314,6 +314,10 @@ export function FlexSetMonLevel(arg1) {
|
||||
return window['go']['main']['App']['FlexSetMonLevel'](arg1);
|
||||
}
|
||||
|
||||
export function FlexSetMute(arg1) {
|
||||
return window['go']['main']['App']['FlexSetMute'](arg1);
|
||||
}
|
||||
|
||||
export function FlexSetNB(arg1) {
|
||||
return window['go']['main']['App']['FlexSetNB'](arg1);
|
||||
}
|
||||
|
||||
@@ -515,6 +515,7 @@ export namespace cat {
|
||||
agc_mode?: string;
|
||||
agc_threshold: number;
|
||||
audio_level: number;
|
||||
mute: boolean;
|
||||
nb: boolean;
|
||||
nb_level: number;
|
||||
nr: boolean;
|
||||
@@ -563,6 +564,7 @@ export namespace cat {
|
||||
this.agc_mode = source["agc_mode"];
|
||||
this.agc_threshold = source["agc_threshold"];
|
||||
this.audio_level = source["audio_level"];
|
||||
this.mute = source["mute"];
|
||||
this.nb = source["nb"];
|
||||
this.nb_level = source["nb_level"];
|
||||
this.nr = source["nr"];
|
||||
|
||||
@@ -251,6 +251,7 @@ type FlexTXState struct {
|
||||
AGCMode string `json:"agc_mode,omitempty"`
|
||||
AGCThreshold int `json:"agc_threshold"`
|
||||
AudioLevel int `json:"audio_level"`
|
||||
Mute bool `json:"mute"`
|
||||
NB bool `json:"nb"`
|
||||
NBLevel int `json:"nb_level"`
|
||||
NR bool `json:"nr"`
|
||||
@@ -312,6 +313,7 @@ type FlexController interface {
|
||||
SetAGCMode(string) error
|
||||
SetAGCThreshold(int) error
|
||||
SetAudioLevel(int) error
|
||||
SetMute(bool) error
|
||||
SetNB(bool) error
|
||||
SetNBLevel(int) error
|
||||
SetNR(bool) error
|
||||
|
||||
@@ -73,6 +73,7 @@ type flexSlice struct {
|
||||
agcMode string // off | slow | med | fast
|
||||
agcThreshold int // 0-100
|
||||
audioLevel int // 0-100 (RX volume)
|
||||
mute bool // RX audio muted
|
||||
nb bool // noise blanker
|
||||
nbLevel int
|
||||
nr bool // noise reduction
|
||||
@@ -670,6 +671,8 @@ func (f *Flex) handleStatus(payload string) {
|
||||
s.agcThreshold = atoiDefault(val, s.agcThreshold)
|
||||
case "audio_level":
|
||||
s.audioLevel = atoiDefault(val, s.audioLevel)
|
||||
case "audio_mute", "mute":
|
||||
s.mute = val == "1"
|
||||
case "nb":
|
||||
s.nb = val == "1"
|
||||
case "nb_level":
|
||||
@@ -1029,6 +1032,7 @@ func (f *Flex) FlexState() FlexTXState {
|
||||
st.AGCMode = rx.agcMode
|
||||
st.AGCThreshold = rx.agcThreshold
|
||||
st.AudioLevel = rx.audioLevel
|
||||
st.Mute = rx.mute
|
||||
st.NB = rx.nb
|
||||
st.NBLevel = rx.nbLevel
|
||||
st.NR = rx.nr
|
||||
@@ -1076,6 +1080,8 @@ func (f *Flex) sendSlice(param string, val any) error {
|
||||
rx.agcThreshold = toInt(val)
|
||||
case "audio_level":
|
||||
rx.audioLevel = toInt(val)
|
||||
case "audio_mute", "mute":
|
||||
rx.mute = fmt.Sprint(val) == "1"
|
||||
case "nb":
|
||||
rx.nb = val == "1"
|
||||
case "nb_level":
|
||||
@@ -1126,6 +1132,7 @@ func (f *Flex) SetAGCMode(m string) error {
|
||||
}
|
||||
func (f *Flex) SetAGCThreshold(l int) error { return f.sendSlice("agc_threshold", clampLevel(l)) }
|
||||
func (f *Flex) SetAudioLevel(l int) error { return f.sendSlice("audio_level", clampLevel(l)) }
|
||||
func (f *Flex) SetMute(on bool) error { return f.sendSlice("audio_mute", boolFlex(on)) }
|
||||
func (f *Flex) SetNB(on bool) error { return f.sendSlice("nb", boolFlex(on)) }
|
||||
func (f *Flex) SetNBLevel(l int) error { return f.sendSlice("nb_level", clampLevel(l)) }
|
||||
func (f *Flex) SetNR(on bool) error { return f.sendSlice("nr", boolFlex(on)) }
|
||||
|
||||
Reference in New Issue
Block a user