Issue #375: pause-then-resume sometimes leaves audio silent. Diagnosis
in user-reported logs:
Synced audio settings to CoreBridge player: backend=None, exclusive=false
...
Resume: reinitializing stream at 44100Hz/2ch
Using default audio device <- legacy CPAL path
Using audio device: Default Audio Device
Audio output initialized successfully <- silent stream
backend_type=None falls through to init_device's legacy CPAL path which
races against rodio's DeviceSink drop on resume — CPAL hands us a new
default-device handle, but PipeWire is still tearing down the previous
sink, and the new handle ends up routed to a node that produces no
sound. CPAL doesn't fail the open, just gives a silent stream.
The "Sync audio settings on startup" toggle Rico29 was asked to enable
fires correctly (`sync_audio_on_startup=true` in his log) but only
re-syncs whatever is persisted. His persisted backend_type was still
NULL because he never explicitly picked a backend, so the sync was a
no-op.
Fix:
- Default::default() now sets backend_type to Some(AudioBackendType::default()),
which picks PipeWire on Linux and SystemDefault elsewhere. New installs
go directly onto the proper backend init path; the runtime still
degrades gracefully if the chosen backend isn't available on the host
(try_init_stream_with_backend returns Some(Err(_)) and the existing
fallback warning fires).
- Migration backfills existing rows where backend_type IS NULL with the
same per-OS default, serialized via serde_json so the row read path
round-trips cleanly. macOS users were already getting effective
SystemDefault dynamically at the call site (audio_settings.backend_type
.or_else(...)) so behaviour there is unchanged; the migration just
persists what the runtime was already substituting.
reset_all picks up the new default automatically because it reads
AudioSettings::default().backend_type.
cc