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) })
|
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 {
|
func (a *App) FlexSetNB(on bool) error {
|
||||||
if a.cat == nil {
|
if a.cat == nil {
|
||||||
return fmt.Errorf("cat not initialized")
|
return fmt.Errorf("cat not initialized")
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
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 {
|
import {
|
||||||
GetFlexState, FlexSetPower, FlexSetTunePower, FlexTune, FlexSetVox, FlexSetVoxLevel, FlexSetVoxDelay,
|
GetFlexState, FlexSetPower, FlexSetTunePower, FlexTune, FlexSetVox, FlexSetVoxLevel, FlexSetVoxDelay,
|
||||||
FlexSetProcessor, FlexSetProcessorLevel, FlexSetMon, FlexSetMonLevel, FlexSetMic,
|
FlexSetProcessor, FlexSetProcessorLevel, FlexSetMon, FlexSetMonLevel, FlexSetMic,
|
||||||
FlexMox, FlexAmpOperate,
|
FlexMox, FlexAmpOperate,
|
||||||
GetPGXLStatus, PGXLSetFanMode,
|
GetPGXLStatus, PGXLSetFanMode,
|
||||||
FlexSetAGCMode, FlexSetAGCThreshold, FlexSetAudioLevel,
|
FlexSetAGCMode, FlexSetAGCThreshold, FlexSetAudioLevel, FlexSetMute,
|
||||||
FlexSetNB, FlexSetNBLevel, FlexSetNR, FlexSetNRLevel, FlexSetANF, FlexSetANFLevel,
|
FlexSetNB, FlexSetNBLevel, FlexSetNR, FlexSetNRLevel, FlexSetANF, FlexSetANFLevel,
|
||||||
FlexSetAPF, FlexSetAPFLevel, FlexSetCWSpeed, FlexSetCWPitch, FlexSetCWBreakInDelay,
|
FlexSetAPF, FlexSetAPFLevel, FlexSetCWSpeed, FlexSetCWPitch, FlexSetCWBreakInDelay,
|
||||||
FlexSetCWSidetone, FlexSetSidetoneLevel, FlexSetCWFilter, FlexSetFilter,
|
FlexSetCWSidetone, FlexSetSidetoneLevel, FlexSetCWFilter, FlexSetFilter,
|
||||||
@@ -19,7 +19,7 @@ type FlexState = {
|
|||||||
proc_enable: boolean; proc_level: number;
|
proc_enable: boolean; proc_level: number;
|
||||||
mon: boolean; mon_level: number; mic_level: number;
|
mon: boolean; mon_level: number; mic_level: number;
|
||||||
atu_status?: string; atu_memories: boolean;
|
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;
|
nb: boolean; nb_level: number; nr: boolean; nr_level: number; anf: boolean; anf_level: number;
|
||||||
mode?: string;
|
mode?: string;
|
||||||
cw_speed: number; cw_pitch: number; cw_break_in_delay: number; cw_sidetone: boolean; cw_mon_level: number;
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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))} />
|
onChange={(v) => change('agc_mode', v, () => FlexSetAGCMode(v))} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">Thresh</span>
|
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AF</span>
|
||||||
<Slider value={st.agc_threshold} disabled={rxOff} accent="#64748b" onChange={(v) => change('agc_threshold', v, () => FlexSetAGCThreshold(v))} />
|
<button type="button" disabled={rxOff}
|
||||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.agc_threshold}</span>
|
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>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AF</span>
|
<span className="w-14 shrink-0 text-[11px] font-bold text-muted-foreground">AGC-T</span>
|
||||||
<Slider value={st.audio_level} disabled={rxOff} accent="#16a34a" onChange={(v) => change('audio_level', v, () => FlexSetAudioLevel(v))} />
|
<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.audio_level}</span>
|
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.agc_threshold}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-border/60 pt-3 space-y-3">
|
<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"
|
<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 FlexSetMonLevel(arg1:number):Promise<void>;
|
||||||
|
|
||||||
|
export function FlexSetMute(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
export function FlexSetNB(arg1:boolean):Promise<void>;
|
export function FlexSetNB(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
export function FlexSetNBLevel(arg1:number):Promise<void>;
|
export function FlexSetNBLevel(arg1:number):Promise<void>;
|
||||||
|
|||||||
@@ -314,6 +314,10 @@ export function FlexSetMonLevel(arg1) {
|
|||||||
return window['go']['main']['App']['FlexSetMonLevel'](arg1);
|
return window['go']['main']['App']['FlexSetMonLevel'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FlexSetMute(arg1) {
|
||||||
|
return window['go']['main']['App']['FlexSetMute'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function FlexSetNB(arg1) {
|
export function FlexSetNB(arg1) {
|
||||||
return window['go']['main']['App']['FlexSetNB'](arg1);
|
return window['go']['main']['App']['FlexSetNB'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -515,6 +515,7 @@ export namespace cat {
|
|||||||
agc_mode?: string;
|
agc_mode?: string;
|
||||||
agc_threshold: number;
|
agc_threshold: number;
|
||||||
audio_level: number;
|
audio_level: number;
|
||||||
|
mute: boolean;
|
||||||
nb: boolean;
|
nb: boolean;
|
||||||
nb_level: number;
|
nb_level: number;
|
||||||
nr: boolean;
|
nr: boolean;
|
||||||
@@ -563,6 +564,7 @@ export namespace cat {
|
|||||||
this.agc_mode = source["agc_mode"];
|
this.agc_mode = source["agc_mode"];
|
||||||
this.agc_threshold = source["agc_threshold"];
|
this.agc_threshold = source["agc_threshold"];
|
||||||
this.audio_level = source["audio_level"];
|
this.audio_level = source["audio_level"];
|
||||||
|
this.mute = source["mute"];
|
||||||
this.nb = source["nb"];
|
this.nb = source["nb"];
|
||||||
this.nb_level = source["nb_level"];
|
this.nb_level = source["nb_level"];
|
||||||
this.nr = source["nr"];
|
this.nr = source["nr"];
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ type FlexTXState struct {
|
|||||||
AGCMode string `json:"agc_mode,omitempty"`
|
AGCMode string `json:"agc_mode,omitempty"`
|
||||||
AGCThreshold int `json:"agc_threshold"`
|
AGCThreshold int `json:"agc_threshold"`
|
||||||
AudioLevel int `json:"audio_level"`
|
AudioLevel int `json:"audio_level"`
|
||||||
|
Mute bool `json:"mute"`
|
||||||
NB bool `json:"nb"`
|
NB bool `json:"nb"`
|
||||||
NBLevel int `json:"nb_level"`
|
NBLevel int `json:"nb_level"`
|
||||||
NR bool `json:"nr"`
|
NR bool `json:"nr"`
|
||||||
@@ -312,6 +313,7 @@ type FlexController interface {
|
|||||||
SetAGCMode(string) error
|
SetAGCMode(string) error
|
||||||
SetAGCThreshold(int) error
|
SetAGCThreshold(int) error
|
||||||
SetAudioLevel(int) error
|
SetAudioLevel(int) error
|
||||||
|
SetMute(bool) error
|
||||||
SetNB(bool) error
|
SetNB(bool) error
|
||||||
SetNBLevel(int) error
|
SetNBLevel(int) error
|
||||||
SetNR(bool) error
|
SetNR(bool) error
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ type flexSlice struct {
|
|||||||
agcMode string // off | slow | med | fast
|
agcMode string // off | slow | med | fast
|
||||||
agcThreshold int // 0-100
|
agcThreshold int // 0-100
|
||||||
audioLevel int // 0-100 (RX volume)
|
audioLevel int // 0-100 (RX volume)
|
||||||
|
mute bool // RX audio muted
|
||||||
nb bool // noise blanker
|
nb bool // noise blanker
|
||||||
nbLevel int
|
nbLevel int
|
||||||
nr bool // noise reduction
|
nr bool // noise reduction
|
||||||
@@ -670,6 +671,8 @@ func (f *Flex) handleStatus(payload string) {
|
|||||||
s.agcThreshold = atoiDefault(val, s.agcThreshold)
|
s.agcThreshold = atoiDefault(val, s.agcThreshold)
|
||||||
case "audio_level":
|
case "audio_level":
|
||||||
s.audioLevel = atoiDefault(val, s.audioLevel)
|
s.audioLevel = atoiDefault(val, s.audioLevel)
|
||||||
|
case "audio_mute", "mute":
|
||||||
|
s.mute = val == "1"
|
||||||
case "nb":
|
case "nb":
|
||||||
s.nb = val == "1"
|
s.nb = val == "1"
|
||||||
case "nb_level":
|
case "nb_level":
|
||||||
@@ -1029,6 +1032,7 @@ func (f *Flex) FlexState() FlexTXState {
|
|||||||
st.AGCMode = rx.agcMode
|
st.AGCMode = rx.agcMode
|
||||||
st.AGCThreshold = rx.agcThreshold
|
st.AGCThreshold = rx.agcThreshold
|
||||||
st.AudioLevel = rx.audioLevel
|
st.AudioLevel = rx.audioLevel
|
||||||
|
st.Mute = rx.mute
|
||||||
st.NB = rx.nb
|
st.NB = rx.nb
|
||||||
st.NBLevel = rx.nbLevel
|
st.NBLevel = rx.nbLevel
|
||||||
st.NR = rx.nr
|
st.NR = rx.nr
|
||||||
@@ -1076,6 +1080,8 @@ func (f *Flex) sendSlice(param string, val any) error {
|
|||||||
rx.agcThreshold = toInt(val)
|
rx.agcThreshold = toInt(val)
|
||||||
case "audio_level":
|
case "audio_level":
|
||||||
rx.audioLevel = toInt(val)
|
rx.audioLevel = toInt(val)
|
||||||
|
case "audio_mute", "mute":
|
||||||
|
rx.mute = fmt.Sprint(val) == "1"
|
||||||
case "nb":
|
case "nb":
|
||||||
rx.nb = val == "1"
|
rx.nb = val == "1"
|
||||||
case "nb_level":
|
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) 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) 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) 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) SetNBLevel(l int) error { return f.sendSlice("nb_level", clampLevel(l)) }
|
||||||
func (f *Flex) SetNR(on bool) error { return f.sendSlice("nr", boolFlex(on)) }
|
func (f *Flex) SetNR(on bool) error { return f.sendSlice("nr", boolFlex(on)) }
|
||||||
|
|||||||
Reference in New Issue
Block a user