Skip to content

Commit 5fca9d2

Browse files
committed
fix(alsa): prevent double opens with BufferSize::Fixed
1 parent 81b4d65 commit 5fca9d2

1 file changed

Lines changed: 11 additions & 25 deletions

File tree

src/host/alsa/mod.rs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -361,31 +361,6 @@ impl Device {
361361
sample_format: SampleFormat,
362362
stream_type: alsa::Direction,
363363
) -> Result<StreamInner, Error> {
364-
// Validate buffer size if Fixed is specified. This is necessary because
365-
// `set_period_size_near()` with `ValueOr::Nearest` will accept ANY value and return the
366-
// "nearest" supported value, which could be wildly different (e.g., requesting 4096 frames
367-
// might return 512 frames if that's "nearest").
368-
if let BufferSize::Fixed(requested_size) = conf.buffer_size {
369-
// Note: We use `default_input_config`/`default_output_config` to get the buffer size
370-
// range. This queries the CURRENT device (`self.pcm_id`), not the default device. The
371-
// buffer size range is the same across all format configurations for a given device
372-
// (see `supported_configs()`).
373-
let supported_config = match stream_type {
374-
alsa::Direction::Capture => self.default_input_config(),
375-
alsa::Direction::Playback => self.default_output_config(),
376-
};
377-
if let Ok(config) = supported_config {
378-
if let SupportedBufferSize::Range { min, max } = config.buffer_size {
379-
if !(min..=max).contains(&requested_size) {
380-
return Err(Error::with_message(
381-
ErrorKind::UnsupportedConfig,
382-
format!("Buffer size {requested_size} is not in the supported range {min}..={max}"),
383-
));
384-
}
385-
}
386-
}
387-
}
388-
389364
let handle = {
390365
let _guard = ALSA_OPEN_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
391366
alsa::pcm::PCM::new(&self.pcm_id, stream_type, true)?
@@ -1571,6 +1546,17 @@ fn set_hw_params_from_format(
15711546
// buffer_size = 2x and period_size = x. This provides consistent low-latency
15721547
// behavior across different ALSA implementations and hardware.
15731548
if let BufferSize::Fixed(buffer_frames) = config.buffer_size {
1549+
// Validate the requested size against the device's supported range using the same PCM
1550+
// handle we'll use for streaming. This avoids a second PCM open (which can disturb
1551+
// hardware clock state on some drivers) while still catching wildly out-of-range
1552+
// requests before set_period_size_near silently rounds them.
1553+
let (min_buffer, max_buffer) = hw_params_buffer_size_min_max(&hw_params);
1554+
if !(min_buffer..=max_buffer).contains(&buffer_frames) {
1555+
return Err(Error::with_message(
1556+
ErrorKind::UnsupportedConfig,
1557+
format!("Buffer size {buffer_frames} is not in the supported range {min_buffer}..={max_buffer}"),
1558+
));
1559+
}
15741560
hw_params.set_buffer_size_near(DEFAULT_PERIODS * buffer_frames as alsa::pcm::Frames)?;
15751561
hw_params
15761562
.set_period_size_near(buffer_frames as alsa::pcm::Frames, alsa::ValueOr::Nearest)?;

0 commit comments

Comments
 (0)