Skip to content

Commit 66f820c

Browse files
committed
feat(coreaudio): add timeout to set_sample_rate
1 parent 29131bc commit 66f820c

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5454
rate change on macOS, and on iOS on route changes that require a stream rebuild.
5555
- **CoreAudio**: Stream error callback now receives `StreamError::DeviceNotAvailable` on iOS
5656
when media services are lost.
57+
- **CoreAudio**: User timeouts are now obeyed when building a stream.
5758
- **JACK**: Timestamps now use the precise hardware deadline.
5859
- **JACK**: Buffer size change no longer fires an error callback; internal buffers are resized
5960
without error.

src/host/coreaudio/macos/device.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ fn set_physical_format(
9090
fn set_sample_rate(
9191
audio_device_id: AudioObjectID,
9292
target_sample_rate: SampleRate,
93+
timeout: Option<Duration>,
9394
) -> Result<(), BuildStreamError> {
9495
// Get the current sample rate.
9596
let mut property_address = AudioObjectPropertyAddress {
@@ -173,12 +174,15 @@ fn set_sample_rate(
173174
};
174175
coreaudio::Error::from_os_status(status)?;
175176

176-
// Wait for the rate change to be confirmed. Should take a few ms in practice;
177-
// timeout after 1 s as a safety net.
178-
let mut timeout = Duration::from_secs(1);
177+
// Wait for the reported_rate to change.
178+
//
179+
// This should not take longer than a few ms. Use the caller's timeout if provided,
180+
// otherwise default to 1 second. We loop over potentially several events from the
181+
// channel to ensure that we catch the expected change in sample rate.
182+
let mut remaining = timeout.unwrap_or(Duration::from_secs(1));
179183
let start = Instant::now();
180184
loop {
181-
match receiver.recv_timeout(timeout) {
185+
match receiver.recv_timeout(remaining) {
182186
Ok(reported_rate) => {
183187
if (reported_rate - target_sample_rate as f64).abs() < 1.0 {
184188
break;
@@ -199,7 +203,7 @@ fn set_sample_rate(
199203
.into());
200204
}
201205
}
202-
timeout = timeout
206+
remaining = remaining
203207
.checked_sub(start.elapsed())
204208
.unwrap_or(Duration::ZERO);
205209
}
@@ -742,7 +746,7 @@ impl Device {
742746
sample_format: SampleFormat,
743747
mut data_callback: D,
744748
error_callback: E,
745-
_timeout: Option<Duration>,
749+
timeout: Option<Duration>,
746750
) -> Result<Stream, BuildStreamError>
747751
where
748752
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
@@ -763,7 +767,7 @@ impl Device {
763767
)
764768
.is_err()
765769
{
766-
set_sample_rate(self.audio_device_id, config.sample_rate)?;
770+
set_sample_rate(self.audio_device_id, config.sample_rate, timeout)?;
767771
}
768772

769773
let mut loopback_aggregate: Option<LoopbackDevice> = None;
@@ -857,7 +861,7 @@ impl Device {
857861
sample_format: SampleFormat,
858862
mut data_callback: D,
859863
error_callback: E,
860-
_timeout: Option<Duration>,
864+
timeout: Option<Duration>,
861865
) -> Result<Stream, BuildStreamError>
862866
where
863867
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
@@ -874,7 +878,7 @@ impl Device {
874878
)
875879
.is_err()
876880
{
877-
set_sample_rate(self.audio_device_id, config.sample_rate)?;
881+
set_sample_rate(self.audio_device_id, config.sample_rate, timeout)?;
878882
}
879883

880884
let mut audio_unit = audio_unit_from_device(self, false)?;

0 commit comments

Comments
 (0)