Compare commits

..

1 Commits

Author SHA1 Message Date
Alex fbee0b2925
Merge cd7a098f76 into 204909b49a 2025-10-28 15:47:54 +02:00
6 changed files with 28 additions and 50 deletions

View File

@ -22,7 +22,7 @@ var (
audioLogger zerolog.Logger
currentAudioTrack *webrtc.TrackLocalStaticSample
inputTrackHandling atomic.Bool
useUSBForAudioOutput atomic.Bool
useUSBForAudioOutput bool
audioOutputEnabled atomic.Bool
audioInputEnabled atomic.Bool
)
@ -32,7 +32,7 @@ func initAudio() {
// Load audio output source from config
ensureConfigLoaded()
useUSBForAudioOutput.Store(config.AudioOutputSource == "usb")
useUSBForAudioOutput = config.AudioOutputSource == "usb"
// Enable both by default
audioOutputEnabled.Store(true)
@ -57,7 +57,7 @@ func startAudio() error {
// Start output audio if not running and enabled
if outputSource == nil && audioOutputEnabled.Load() {
alsaDevice := "hw:0,0" // HDMI
if useUSBForAudioOutput.Load() {
if useUSBForAudioOutput {
alsaDevice = "hw:1,0" // USB
}
@ -167,17 +167,16 @@ func SetAudioOutputSource(useUSB bool) error {
audioMutex.Lock()
defer audioMutex.Unlock()
if useUSBForAudioOutput.Load() == useUSB {
if useUSBForAudioOutput == useUSB {
return nil
}
audioLogger.Info().
Bool("old_usb", useUSBForAudioOutput.Load()).
Bool("old_usb", useUSBForAudioOutput).
Bool("new_usb", useUSB).
Msg("Switching audio output source")
oldValue := useUSBForAudioOutput.Load()
useUSBForAudioOutput.Store(useUSB)
useUSBForAudioOutput = useUSB
ensureConfigLoaded()
if useUSB {
@ -187,7 +186,6 @@ func SetAudioOutputSource(useUSB bool) error {
}
if err := SaveConfig(); err != nil {
audioLogger.Error().Err(err).Msg("Failed to save config")
useUSBForAudioOutput.Store(oldValue)
return err
}

View File

@ -305,11 +305,11 @@ func wakeDisplay(force bool, reason string) {
displayLogger.Warn().Err(err).Msg("failed to wake display")
}
if config.DisplayDimAfterSec != 0 && dimTicker != nil {
if config.DisplayDimAfterSec != 0 {
dimTicker.Reset(time.Duration(config.DisplayDimAfterSec) * time.Second)
}
if config.DisplayOffAfterSec != 0 && offTicker != nil {
if config.DisplayOffAfterSec != 0 {
offTicker.Reset(time.Duration(config.DisplayOffAfterSec) * time.Second)
}
backlightState = 0

View File

@ -20,8 +20,7 @@ type OutputRelay struct {
cancel context.CancelFunc
logger zerolog.Logger
running atomic.Bool
sample media.Sample
stopped chan struct{}
sample media.Sample // Reusable sample for zero-allocation hot path
// Stats (Uint32: overflows after 2.7 years @ 50fps, faster atomics on 32-bit ARM)
framesRelayed atomic.Uint32
@ -39,9 +38,8 @@ func NewOutputRelay(source AudioSource, audioTrack *webrtc.TrackLocalStaticSampl
ctx: ctx,
cancel: cancel,
logger: logger,
stopped: make(chan struct{}),
sample: media.Sample{
Duration: 20 * time.Millisecond,
Duration: 20 * time.Millisecond, // Constant for all Opus frames
},
}
}
@ -57,15 +55,13 @@ func (r *OutputRelay) Start() error {
return nil
}
// Stop stops the relay and waits for goroutine to exit
// Stop stops the relay
func (r *OutputRelay) Stop() {
if !r.running.Swap(false) {
return
}
r.cancel()
<-r.stopped
r.logger.Debug().
Uint32("frames_relayed", r.framesRelayed.Load()).
Uint32("frames_dropped", r.framesDropped.Load()).
@ -74,8 +70,6 @@ func (r *OutputRelay) Stop() {
// relayLoop continuously reads from audio source and writes to WebRTC
func (r *OutputRelay) relayLoop() {
defer close(r.stopped)
const reconnectDelay = 1 * time.Second
for r.running.Load() {

View File

@ -899,7 +899,7 @@ func updateUsbRelatedConfig(wasAudioEnabled bool) error {
if config.UsbDevices != nil && !config.UsbDevices.Audio && config.AudioOutputSource == "usb" {
audioMutex.Lock()
config.AudioOutputSource = "hdmi"
useUSBForAudioOutput.Store(false)
useUSBForAudioOutput = false
audioSourceChanged = true
audioMutex.Unlock()
}
@ -908,7 +908,7 @@ func updateUsbRelatedConfig(wasAudioEnabled bool) error {
if config.UsbDevices != nil && config.UsbDevices.Audio && !wasAudioEnabled {
audioMutex.Lock()
config.AudioOutputSource = "usb"
useUSBForAudioOutput.Store(true)
useUSBForAudioOutput = true
audioSourceChanged = true
audioMutex.Unlock()
}
@ -970,10 +970,8 @@ func rpcSetUsbDeviceState(device string, enabled bool) error {
}
func rpcGetAudioOutputSource() (string, error) {
if useUSBForAudioOutput.Load() {
return "usb", nil
}
return "hdmi", nil
ensureConfigLoaded()
return config.AudioOutputSource, nil
}
func rpcSetAudioOutputSource(source string) error {

View File

@ -111,7 +111,6 @@ type Client struct {
var (
defaultTimerDuration = 1 * time.Second
defaultLinkUpTimeout = 30 * time.Second
defaultDHCPTimeout = 5 * time.Second // DHCP request timeout (not link up timeout)
maxRenewalAttemptDuration = 2 * time.Hour
)
@ -126,11 +125,11 @@ func NewClient(ctx context.Context, ifaces []string, c *Config, l *zerolog.Logge
}
if cfg.Timeout == 0 {
cfg.Timeout = defaultDHCPTimeout
cfg.Timeout = defaultLinkUpTimeout
}
if cfg.Retries == 0 {
cfg.Retries = 4
cfg.Retries = 3
}
return &Client{
@ -154,15 +153,9 @@ func NewClient(ctx context.Context, ifaces []string, c *Config, l *zerolog.Logge
}, nil
}
func resetTimer(t *time.Timer, attempt int, l *zerolog.Logger) {
// Exponential backoff: 1s, 2s, 4s, 8s, max 8s
backoffAttempt := attempt
if backoffAttempt > 3 {
backoffAttempt = 3
}
delay := time.Duration(1<<backoffAttempt) * time.Second
l.Debug().Dur("delay", delay).Int("attempt", attempt).Msg("will retry later")
t.Reset(delay)
func resetTimer(t *time.Timer, l *zerolog.Logger) {
l.Debug().Dur("delay", defaultTimerDuration).Msg("will retry later")
t.Reset(defaultTimerDuration)
}
func getRenewalTime(lease *Lease) time.Duration {
@ -175,14 +168,12 @@ func getRenewalTime(lease *Lease) time.Duration {
func (c *Client) requestLoop(t *time.Timer, family int, ifname string) {
l := c.l.With().Str("interface", ifname).Int("family", family).Logger()
attempt := 0
for range t.C {
l.Info().Int("attempt", attempt).Msg("requesting lease")
l.Info().Msg("requesting lease")
if _, err := c.ensureInterfaceUp(ifname); err != nil {
l.Error().Err(err).Int("attempt", attempt).Msg("failed to ensure interface up")
resetTimer(t, attempt, c.l)
attempt++
l.Error().Err(err).Msg("failed to ensure interface up")
resetTimer(t, c.l)
continue
}
@ -197,14 +188,11 @@ func (c *Client) requestLoop(t *time.Timer, family int, ifname string) {
lease, err = c.requestLease6(ifname)
}
if err != nil {
l.Error().Err(err).Int("attempt", attempt).Msg("failed to request lease")
resetTimer(t, attempt, c.l)
attempt++
l.Error().Err(err).Msg("failed to request lease")
resetTimer(t, c.l)
continue
}
// Successfully obtained lease, reset attempt counter
attempt = 0
c.handleLeaseChange(lease)
nextRenewal := getRenewalTime(lease)

View File

@ -46,10 +46,10 @@ export default function SettingsHardwareRoute() {
}
setBacklightSettings(settings);
handleBacklightSettingsSave(settings);
handleBacklightSettingsSave();
};
const handleBacklightSettingsSave = (backlightSettings: BacklightSettings) => {
const handleBacklightSettingsSave = () => {
send("setBacklightSettings", { params: backlightSettings }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(