Repository navigation
fix(platform-audio): synthesize index GUIDs on Linux and support index-based selection - #1529
Conversation
…x-based selection (livekit#1528)
There was a problem hiding this comment.
Devin Review found 2 potential issues.
3 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
| let success = if let Some(idx_str) = guid.strip_prefix("index:") { | ||
| if let Ok(idx) = idx_str.parse::<u16>() { | ||
| self.handle.runtime.set_recording_device(idx) |
There was a problem hiding this comment.
🟡 Index IDs fail on GUID-backed devices
On GUID-backed desktops, set_recording_device rejects from_index(0) before selecting the device. recording_devices exposes hardware GUIDs, so its ID check cannot match the index ID. The same failure affects recording switches and playout selection.
Learn more
The new public from_index constructors create IDs intended to select a device by index. On platforms where enumeration returns hardware GUIDs, ensure_device_exists compares these constructed IDs with GUID-backed IDs and rejects them before the index branch executes. This affects both set methods and recording switches. Playout switches lack that check and therefore behave differently.
Example: A Windows microphone at index 0 has GUID mic-123. RecordingDeviceId::from_index(0) creates index:0; set_recording_device returns DeviceNotFound despite the device existing, while set_recording_device_by_index(0) succeeds.
Recommended fix: Validate parsed index IDs against the current device count instead of comparing them to enumerated GUIDs, and apply the same approach to both set and switch paths for recording and playout.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if (target_guid.empty()) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
🟡 Existing Android device IDs stop working
When an Android client reuses its previously enumerated empty ID, set_playout_device_by_guid rejects it. The former default-device fallback accepted that ID, so persisted selections now fail despite an available device. Recording selection has the same regression.
Learn more
Android previously reported an empty device ID. The selection methods previously searched empty GUIDs and then fell back to device 0 when none matched. Callers, including the FFI selection handlers, can supply such previously enumerated IDs. The new unconditional empty-string rejection prevents mobile fallback, so upgrading breaks existing saved selections.
Example: An Android app saved its speaker ID as "" before upgrading. After upgrading, it passes that ID to set_playout_device; the call returns DeviceNotFound although the default speaker is available.
Recommended fix: Retain the existing empty-ID default-device behavior for mobile platforms only; reject empty IDs on desktop. Apply the same fix to recording and playout.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
Thanks for fixing it. |
Fixes #1528.
Problem
On Linux with PulseAudio/ALSA, WebRTC's audio device module does not populate device GUIDs (
device_guidis left empty""). As a result,PlatformAudio::recording_devices()andplayout_devices()return devices with empty IDs (RecordingDeviceId("")).When selecting or switching devices via
set_recording_device/switch_recording_device(or playout equivalents),set_*_device_by_guidmatches"" == ""on index0, which always selects the default device0and makes it impossible to select secondary microphones or speakers on Linux.Solution
webrtc-sys(AudioDeviceController):recording_device_guidandplayout_device_guid, when the underlying ADM does not provide a hardware GUID (guid[0] == '\0'), synthesize an index-based identifier ("index:" + std::to_string(index)) so devices can be uniquely distinguished and selected.set_recording_device_by_guidandset_playout_device_by_guid:return false)."index:<N>"identifiers to device indices with bounds checking.device_guids only (preventing false-positive matches whendevice_guidis empty).WEBRTC_IOS/WEBRTC_ANDROID) where device selection is handled by the system.livekit(PlatformAudio):RecordingDeviceId::from_indexandPlayoutDeviceId::from_index.RecordingDeviceInfoandPlayoutDeviceInfo, fall back tofrom_indexifguid.is_empty()."index:<N>"inset_recording_device,set_playout_device,switch_recording_device, andswitch_playout_device.set_recording_device_by_index,set_playout_device_by_index,switch_recording_device_by_index, andswitch_playout_device_by_index.livekit/src/platform_audio/mod.rsforfrom_indexand equality/hashing.livekit/tests/platform_audio_test.rsfor index-based selection and out-of-bounds error handling.webrtc-sysbridge test.livekit,webrtc-sys,libwebrtc,livekit-capture, andlivekit-ffi.