Files
codex/codex-rs/voice-host/src/devices_unavailable.rs
Benjamin Carlssonandcopyberry fc81a7154b Add local audio device selection to TUI voice settings (#49437)
## Why

Voice conversations previously opened the system-default microphone and speaker. Users need to choose which local devices to use, including when connected to a remote app server.

## What changed

- Add input and output device pickers alongside voice selection, with back navigation and a System default option.
- Persist selections as `audio.microphone` and `audio.speaker` on the TUI's machine, excluding project configuration layers. Apply them to the next voice conversation.
- Enumerate devices without opening audio streams and pass the selected names to the voice helper at startup.
- Disable ambiguous device names in the picker and use the same eligibility filtering for discovery and named-device startup.

## Testing

Add tests for device preference persistence across project and remote transitions, picker navigation and duplicate names, discovery without capture, and forwarding selected devices to the helper.

GitOrigin-RevId: d48fb3a09fa9b982a408f5a7c96bdd81776af21d
2026-09-30 01:58:03 +00:00

41 lines
1.2 KiB
Rust

//! Keep non-native helper targets buildable without linking a host audio backend.
use std::io;
pub(super) fn list_devices(
_: codex_realtime_webrtc::AudioDeviceKind,
) -> io::Result<Vec<codex_realtime_webrtc::AudioDevice>> {
Err(io::Error::other(
"audio devices unavailable for this helper target",
))
}
pub(super) struct Devices;
impl Devices {
pub(super) fn receive(&self, _: crate::incoming::ReceivedRtp) -> io::Result<()> {
Self::open(Default::default()).map(|_| ())
}
pub(super) fn take_state(&self) -> io::Result<codex_realtime_webrtc::AudioState> {
Self::open(Default::default()).map(|_| codex_realtime_webrtc::AudioState::default())
}
pub(super) fn open(_: codex_realtime_webrtc::AudioDeviceSelection) -> io::Result<Self> {
Err(io::Error::other(
"audio devices unavailable for this helper target",
))
}
pub(super) fn set_controls(&self, _: codex_realtime_webrtc::AudioControls) -> io::Result<()> {
Self::open(Default::default()).map(|_| ())
}
pub(super) async fn service(
&mut self,
_: &mut crate::audio_track::AudioTrack,
) -> io::Result<usize> {
Self::open(Default::default()).map(|_| 0)
}
}