feat(audio): audio output device selection (closes #169)

Adds the ability to choose which audio output device Psysonic plays
through — useful for USB DACs, dedicated soundcards, and multi-device setups.

Rust (audio.rs):
- open_stream_for_device_and_rate(device_name, rate): opens a named
  device by cpal name, falls back to system default if not found
- AudioEngine.selected_device: persists the chosen device across
  stream reopens so hi-res rate switches stay on the right device
- audio_list_devices: Tauri command — returns all output device names
- audio_set_device: Tauri command — switches device immediately,
  drops old sinks, emits audio:device-changed
- start_device_watcher: now handles two cases:
    1. No pinned device + system default changed → reopen on new default
    2. Pinned device disappeared (DAC unplugged) → clear selected_device,
       fall back to system default, emit audio:device-reset

Frontend:
- authStore: audioOutputDevice (string | null), persisted
- playerStore: applies stored device on cold start
- App.tsx: listens to audio:device-reset, clears authStore device
  and restarts playback on the fallback device
- Settings → Audio tab: device dropdown at top (above Hi-Res and EQ),
  uses CustomSelect (portal-based, styled), all 8 locales
- CustomSelect: added disabled prop

Note: exclusive mode (WASAPI exclusive, CoreAudio exclusive) is out
of scope for now.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-13 18:20:23 +02:00
parent 9b22327bb0
commit 16cb4f5a6f
15 changed files with 253 additions and 66 deletions
+3
View File
@@ -500,6 +500,9 @@ export const nbTranslation = {
hotCacheDebounceImmediate: 'Umiddelbart',
hotCacheDebounceSeconds: '{{n}} sek',
hotCacheClearBtn: 'Tøm varm buffer',
audioOutputDevice: 'Lydutgangsenhet',
audioOutputDeviceDesc: 'Velg hvilken lydenhet Psysonic spiller gjennom. Endringer trer i kraft umiddelbart og starter gjeldende spor på nytt.',
audioOutputDeviceDefault: 'Systemstandard',
hiResTitle: 'Innebygd hi-res-avspilling',
hiResEnabled: 'Aktiver innebygd hi-res-avspilling',
hiResDesc: "Begrenser utdata til 44,1 kHz som standard for maksimal stabilitet. Aktiver kun hvis maskinvare og nettverk støtter høye samplingsrater (88,2 kHz+) pålitelig.",