Skip to content

Let a microphone's error callback be set - #931

Open
crmne wants to merge 1 commit into
RustAudio:masterfrom
crmne:microphone-error-callback
Open

crmne wants to merge 1 commit into
RustAudio:masterfrom
crmne:microphone-error-callback

Conversation

@crmne

@crmne crmne commented Oct 15, 2026

Copy link
Copy Markdown

MicrophoneBuilder carries an error callback type but has no way to set one, so every microphone uses the default, which prints each stream error to stderr. An application that wants to log errors its own way, rate-limit them, or close a stream that keeps failing has no way in.

This adds MicrophoneBuilder::with_error_callback, matching DeviceSinkBuilder::with_error_callback. It keeps the device and config already set and changes only the callback type. A unit test checks that the callback set on the builder is the one that gets called; there is a CHANGELOG entry under Unreleased.

We hit this in ZapFast (crmne/zapfast#507): a failing ALSA stream reported the same error tens of thousands of times a second, and the output side could be rate-limited while the microphone side could not. SpeakersBuilder has the same gap; I left it out to keep this small, and can add it here if you prefer.

MicrophoneBuilder carries an error callback but has no way to set one, so
every microphone prints each stream error to stderr. An application that
wants to log them its own way, rate-limit them, or close a stream that
keeps failing cannot. Add with_error_callback, as DeviceSinkBuilder has.
Comment thread src/microphone/builder.rs
let builder = MicrophoneBuilder::new().with_error_callback(move |_| {
counted.fetch_add(1, Ordering::Relaxed);
});
let mut callback = builder.error_callback.clone();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this test is particularly helpful, it's not really testing anything just moving a callback into and out of rodio. I'm okay with scrapping it unless you can figure out a good way to cause a cpal failure and observe the results (everywhere this runs and in CI).

Comment thread src/microphone/builder.rs
/// ```no_run
/// # use rodio::microphone::MicrophoneBuilder;
/// let builder = MicrophoneBuilder::new()
/// .with_error_callback(|err| eprintln!("microphone: {err}"));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now this example just implements the default error handling. Can you think of something closer to what a user would want? Maybe store the last error in a global or shove it into an mpsc? I haven't thought about this but it seems you have since you've opened this PR :3

@yara-blue

Copy link
Copy Markdown
Member

Thanks for the PR a nice addition that fits the builder well, think we planned to do this at some point but it slipped through.

SpeakersBuilder has the same gap; I left it out to keep this small, and can add it here if you prefer.

Would be most welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants