temp: disable audio source selection while HDMI audio issues are diagnosed

Temporarily remove the ability to switch between HDMI and USB audio
output sources. The application now uses USB audio (hw:1,0) exclusively
until HDMI audio capture issues are resolved.

Changes:
- Remove AudioOutputSource config field
- Remove audio source switching logic and UI
- Hardcode USB audio output device
- Remove related RPC methods
This commit is contained in:
Alex P 2025-11-03 10:49:35 +02:00
parent de74ae1a12
commit 14b741c3dd
5 changed files with 18 additions and 187 deletions

View File

@ -12,35 +12,27 @@ import (
) )
var ( var (
audioMutex sync.Mutex audioMutex sync.Mutex
outputSource audio.AudioSource outputSource audio.AudioSource
inputSource audio.AudioSource inputSource audio.AudioSource
outputRelay *audio.OutputRelay outputRelay *audio.OutputRelay
inputRelay *audio.InputRelay inputRelay *audio.InputRelay
audioInitialized bool audioInitialized bool
activeConnections atomic.Int32 activeConnections atomic.Int32
audioLogger zerolog.Logger audioLogger zerolog.Logger
currentAudioTrack *webrtc.TrackLocalStaticSample currentAudioTrack *webrtc.TrackLocalStaticSample
inputTrackHandling atomic.Bool inputTrackHandling atomic.Bool
useUSBForAudioOutput atomic.Bool audioOutputEnabled atomic.Bool
audioOutputEnabled atomic.Bool audioInputEnabled atomic.Bool
audioInputEnabled atomic.Bool
) )
func initAudio() { func initAudio() {
audioLogger = logging.GetDefaultLogger().With().Str("component", "audio-manager").Logger() audioLogger = logging.GetDefaultLogger().With().Str("component", "audio-manager").Logger()
// Load audio output source from config
ensureConfigLoaded()
useUSBForAudioOutput.Store(config.AudioOutputSource == "usb")
// Enable both by default
audioOutputEnabled.Store(true) audioOutputEnabled.Store(true)
audioInputEnabled.Store(true) audioInputEnabled.Store(true)
audioLogger.Debug(). audioLogger.Debug().Msg("Audio subsystem initialized")
Str("source", config.AudioOutputSource).
Msg("Audio subsystem initialized")
audioInitialized = true audioInitialized = true
} }
@ -56,12 +48,8 @@ func startAudio() error {
// Start output audio if not running and enabled // Start output audio if not running and enabled
if outputSource == nil && audioOutputEnabled.Load() { if outputSource == nil && audioOutputEnabled.Load() {
alsaDevice := "hw:0,0" // HDMI alsaDevice := "hw:1,0" // USB audio
if useUSBForAudioOutput.Load() {
alsaDevice = "hw:1,0" // USB
}
// Create CGO audio source
outputSource = audio.NewCgoOutputSource(alsaDevice) outputSource = audio.NewCgoOutputSource(alsaDevice)
if currentAudioTrack != nil { if currentAudioTrack != nil {
@ -162,51 +150,6 @@ func setAudioTrack(audioTrack *webrtc.TrackLocalStaticSample) {
} }
} }
// SetAudioOutputSource switches between HDMI and USB audio output
func SetAudioOutputSource(useUSB bool) error {
audioMutex.Lock()
defer audioMutex.Unlock()
if useUSBForAudioOutput.Load() == useUSB {
return nil
}
audioLogger.Info().
Bool("old_usb", useUSBForAudioOutput.Load()).
Bool("new_usb", useUSB).
Msg("Switching audio output source")
oldValue := useUSBForAudioOutput.Load()
useUSBForAudioOutput.Store(useUSB)
ensureConfigLoaded()
if useUSB {
config.AudioOutputSource = "usb"
} else {
config.AudioOutputSource = "hdmi"
}
if err := SaveConfig(); err != nil {
audioLogger.Error().Err(err).Msg("Failed to save config")
useUSBForAudioOutput.Store(oldValue)
return err
}
stopOutputLocked()
// Restart if there are active connections
if activeConnections.Load() > 0 {
audioMutex.Unlock()
err := startAudio()
audioMutex.Lock()
if err != nil {
audioLogger.Error().Err(err).Msg("Failed to restart audio output")
return err
}
}
return nil
}
func setPendingInputTrack(track *webrtc.TrackRemote) { func setPendingInputTrack(track *webrtc.TrackRemote) {
audioMutex.Lock() audioMutex.Lock()
defer audioMutex.Unlock() defer audioMutex.Unlock()

View File

@ -107,7 +107,6 @@ type Config struct {
DefaultLogLevel string `json:"default_log_level"` DefaultLogLevel string `json:"default_log_level"`
VideoSleepAfterSec int `json:"video_sleep_after_sec"` VideoSleepAfterSec int `json:"video_sleep_after_sec"`
VideoQualityFactor float64 `json:"video_quality_factor"` VideoQualityFactor float64 `json:"video_quality_factor"`
AudioOutputSource string `json:"audio_output_source"` // "hdmi" or "usb"
} }
func (c *Config) GetDisplayRotation() uint16 { func (c *Config) GetDisplayRotation() uint16 {
@ -180,7 +179,6 @@ func getDefaultConfig() Config {
return c return c
}(), }(),
DefaultLogLevel: "INFO", DefaultLogLevel: "INFO",
AudioOutputSource: "usb",
VideoQualityFactor: 1.0, VideoQualityFactor: 1.0,
} }
} }

View File

@ -894,33 +894,9 @@ func rpcGetUsbDevices() (usbgadget.Devices, error) {
func updateUsbRelatedConfig(wasAudioEnabled bool) error { func updateUsbRelatedConfig(wasAudioEnabled bool) error {
ensureConfigLoaded() ensureConfigLoaded()
audioSourceChanged := false // Stop input audio before USB reconfiguration (input uses USB)
// If USB audio is being disabled and audio output source is USB, switch to HDMI
if config.UsbDevices != nil && !config.UsbDevices.Audio && config.AudioOutputSource == "usb" {
audioMutex.Lock()
config.AudioOutputSource = "hdmi"
useUSBForAudioOutput.Store(false)
audioSourceChanged = true
audioMutex.Unlock()
}
// If USB audio is being enabled (was disabled, now enabled), switch to USB
if config.UsbDevices != nil && config.UsbDevices.Audio && !wasAudioEnabled {
audioMutex.Lock()
config.AudioOutputSource = "usb"
useUSBForAudioOutput.Store(true)
audioSourceChanged = true
audioMutex.Unlock()
}
// Stop audio before USB reconfiguration
// Input always uses USB, output depends on audioSourceChanged
audioMutex.Lock() audioMutex.Lock()
stopInputLocked() stopInputLocked()
if audioSourceChanged {
stopOutputLocked()
}
audioMutex.Unlock() audioMutex.Unlock()
if err := gadget.UpdateGadgetConfig(); err != nil { if err := gadget.UpdateGadgetConfig(); err != nil {
@ -931,9 +907,8 @@ func updateUsbRelatedConfig(wasAudioEnabled bool) error {
return fmt.Errorf("failed to save config: %w", err) return fmt.Errorf("failed to save config: %w", err)
} }
// Restart audio if source changed or USB audio is enabled with active connections // Restart audio if USB audio is enabled with active connections
// The relay handles device readiness via retry logic if activeConnections.Load() > 0 && config.UsbDevices != nil && config.UsbDevices.Audio {
if activeConnections.Load() > 0 && (audioSourceChanged || (config.UsbDevices != nil && config.UsbDevices.Audio)) {
if err := startAudio(); err != nil { if err := startAudio(); err != nil {
logger.Warn().Err(err).Msg("Failed to restart audio after USB reconfiguration") logger.Warn().Err(err).Msg("Failed to restart audio after USB reconfiguration")
} }
@ -970,22 +945,6 @@ func rpcSetUsbDeviceState(device string, enabled bool) error {
return updateUsbRelatedConfig(wasAudioEnabled) return updateUsbRelatedConfig(wasAudioEnabled)
} }
func rpcGetAudioOutputSource() (string, error) {
if useUSBForAudioOutput.Load() {
return "usb", nil
}
return "hdmi", nil
}
func rpcSetAudioOutputSource(source string) error {
if source != "hdmi" && source != "usb" {
return fmt.Errorf("invalid audio output source: %s (must be 'hdmi' or 'usb')", source)
}
useUSB := source == "usb"
return SetAudioOutputSource(useUSB)
}
func rpcGetAudioOutputEnabled() (bool, error) { func rpcGetAudioOutputEnabled() (bool, error) {
return audioOutputEnabled.Load(), nil return audioOutputEnabled.Load(), nil
} }
@ -1320,8 +1279,6 @@ var rpcHandlers = map[string]RPCHandler{
"getUsbDevices": {Func: rpcGetUsbDevices}, "getUsbDevices": {Func: rpcGetUsbDevices},
"setUsbDevices": {Func: rpcSetUsbDevices, Params: []string{"devices"}}, "setUsbDevices": {Func: rpcSetUsbDevices, Params: []string{"devices"}},
"setUsbDeviceState": {Func: rpcSetUsbDeviceState, Params: []string{"device", "enabled"}}, "setUsbDeviceState": {Func: rpcSetUsbDeviceState, Params: []string{"device", "enabled"}},
"getAudioOutputSource": {Func: rpcGetAudioOutputSource},
"setAudioOutputSource": {Func: rpcSetAudioOutputSource, Params: []string{"source"}},
"getAudioOutputEnabled": {Func: rpcGetAudioOutputEnabled}, "getAudioOutputEnabled": {Func: rpcGetAudioOutputEnabled},
"setAudioOutputEnabled": {Func: rpcSetAudioOutputEnabled, Params: []string{"enabled"}}, "setAudioOutputEnabled": {Func: rpcSetAudioOutputEnabled, Params: []string{"enabled"}},
"getAudioInputEnabled": {Func: rpcGetAudioInputEnabled}, "getAudioInputEnabled": {Func: rpcGetAudioInputEnabled},

View File

@ -370,8 +370,6 @@ export interface SettingsState {
setVideoContrast: (value: number) => void; setVideoContrast: (value: number) => void;
// Audio settings // Audio settings
audioOutputSource: string;
setAudioOutputSource: (source: string) => void;
audioOutputEnabled: boolean; audioOutputEnabled: boolean;
setAudioOutputEnabled: (enabled: boolean) => void; setAudioOutputEnabled: (enabled: boolean) => void;
audioInputEnabled: boolean; audioInputEnabled: boolean;
@ -425,8 +423,6 @@ export const useSettingsStore = create(
setVideoContrast: (value: number) => set({ videoContrast: value }), setVideoContrast: (value: number) => set({ videoContrast: value }),
// Audio settings with defaults // Audio settings with defaults
audioOutputSource: "usb",
setAudioOutputSource: (source: string) => set({ audioOutputSource: source }),
audioOutputEnabled: true, audioOutputEnabled: true,
setAudioOutputEnabled: (enabled: boolean) => set({ audioOutputEnabled: enabled }), setAudioOutputEnabled: (enabled: boolean) => set({ audioOutputEnabled: enabled }),
audioInputEnabled: true, audioInputEnabled: true,

View File

@ -4,7 +4,7 @@ import { SettingsItem } from "@components/SettingsItem";
import { SettingsPageHeader } from "@components/SettingsPageheader"; import { SettingsPageHeader } from "@components/SettingsPageheader";
import { useSettingsStore } from "@/hooks/stores"; import { useSettingsStore } from "@/hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
import { SelectMenuBasic } from "@components/SelectMenuBasic"; // import { SelectMenuBasic } from "@components/SelectMenuBasic";
import Checkbox from "@components/Checkbox"; import Checkbox from "@components/Checkbox";
import { m } from "@localizations/messages.js"; import { m } from "@localizations/messages.js";
@ -14,15 +14,7 @@ export default function SettingsAudioRoute() {
const { send } = useJsonRpc(); const { send } = useJsonRpc();
const settings = useSettingsStore(); const settings = useSettingsStore();
// Fetch current audio settings on mount
useEffect(() => { useEffect(() => {
send("getAudioOutputSource", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) {
return;
}
settings.setAudioOutputSource(resp.result as string);
});
send("getAudioOutputEnabled", {}, (resp: JsonRpcResponse) => { send("getAudioOutputEnabled", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) { if ("error" in resp) {
return; return;
@ -39,41 +31,6 @@ export default function SettingsAudioRoute() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [send]); }, [send]);
const handleAudioOutputSourceChange = (source: string) => {
// Update UI immediately for better responsiveness
settings.setAudioOutputSource(source);
send("setAudioOutputSource", { source }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
// Revert on error by fetching current value from backend
send("getAudioOutputSource", {}, (getResp: JsonRpcResponse) => {
if ("result" in getResp) {
settings.setAudioOutputSource(getResp.result as string);
}
});
notifications.error(
m.audio_settings_output_source_failed({ error: String(resp.error.data || m.unknown_error()) }),
);
return;
}
// Verify the change was applied by fetching the actual value
send("getAudioOutputSource", {}, (getResp: JsonRpcResponse) => {
if ("result" in getResp) {
const actualSource = getResp.result as string;
settings.setAudioOutputSource(actualSource);
if (actualSource === source) {
notifications.success(m.audio_settings_output_source_success());
} else {
notifications.error(
m.audio_settings_output_source_failed({ error: `Expected ${source}, got ${actualSource}` }),
);
}
}
});
});
};
const handleAudioOutputEnabledChange = (enabled: boolean) => { const handleAudioOutputEnabledChange = (enabled: boolean) => {
send("setAudioOutputEnabled", { enabled }, (resp: JsonRpcResponse) => { send("setAudioOutputEnabled", { enabled }, (resp: JsonRpcResponse) => {
if ("error" in resp) { if ("error" in resp) {
@ -121,26 +78,6 @@ export default function SettingsAudioRoute() {
/> />
</SettingsItem> </SettingsItem>
{settings.audioOutputEnabled && (
<SettingsItem
title={m.audio_settings_output_source_title()}
description={m.audio_settings_output_source_description()}
>
<SelectMenuBasic
size="SM"
label=""
value={settings.audioOutputSource || "usb"}
options={[
{ value: "hdmi", label: m.audio_settings_hdmi_label() },
{ value: "usb", label: m.audio_settings_usb_label() },
]}
onChange={e => {
handleAudioOutputSourceChange(e.target.value);
}}
/>
</SettingsItem>
)}
<SettingsItem <SettingsItem
title={m.audio_settings_input_title()} title={m.audio_settings_input_title()}
description={m.audio_settings_input_description()} description={m.audio_settings_input_description()}