Skip to content

Channel names: CoreAudio and ASIO - #1254

Open
nico-franco-gomez wants to merge 4 commits into
RustAudio:developfrom
nico-franco-gomez:feature/channel-names-coreaudio-asio
Open

Channel names: CoreAudio and ASIO#1254
nico-franco-gomez wants to merge 4 commits into
RustAudio:developfrom
nico-franco-gomez:feature/channel-names-coreaudio-asio

Conversation

@nico-franco-gomez

Copy link
Copy Markdown
Contributor

This PR refers to this issue.

I implemented a version of this to showcase how I imagined it. When I wrote the issue, I hadn't realized that the error convention had changed from 0.16 to 0.17. This PR adheres to the current error convention.

@roderickvd

Copy link
Copy Markdown
Member

Sorry for the late reply on this one.

I think this is a worthwhile addition as a trait method. You could add a default implementation to the trait method to prevent the duplication at each backend that doesn't support it.

Before we go further, could you rebase this onto the develop branch? We're staging upcoming feature work there rather than master right now. I intend to promote it to master for a v0.19 release after we push out a v0.18.2 bug fix release.

Happy to take a deeper look once it's rebased!

@nico-franco-gomez
nico-franco-gomez force-pushed the feature/channel-names-coreaudio-asio branch from c27ac0a to f2ba085 Compare July 23, 2026 17:55
@nico-franco-gomez
nico-franco-gomez changed the base branch from master to develop July 23, 2026 17:55
doc

# Conflicts:
#	src/platform/mod.rs
#	src/traits.rs

introduce default implementation

a

update example device
@nico-franco-gomez
nico-franco-gomez force-pushed the feature/channel-names-coreaudio-asio branch from f2ba085 to 8374eff Compare July 23, 2026 17:57
@nico-franco-gomez

Copy link
Copy Markdown
Contributor Author

No problem regarding the delay.

I rebased and implemented the comments while trying to keep a compact, readable git history. Not sure why that specific Linux check is failing, though...

@roderickvd roderickvd left a comment

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.

Thanks again, please find my first review attached.

I've promoted develop to master, so please rebase on master where we'll continue the 0.19.0 work. This should be easier to the last rebase, as it's just continuing the develop branch under a new name, basically.


fn get_channel_name_for_device(
device_id: AudioDeviceID,
channel_index: u16,

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.

Querying an out-of-range channel_index will return a BackendError I think, when InvalidInput would be preferred.

Comment thread src/host/asio/device.rs
.collect();

let input_channel_names: Box<[String]> = (0..channels.ins)
.map(|ch| driver.channel_name(ch, true).unwrap_or_default())

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.

Question: rather than defaulting to an empty string, what if we returned something recognizable like "Channel {ch}"?

pub fn channel_name(&self, channel: i32, is_input: bool) -> Result<String, AsioError> {
let _guard = self.inner.lock_state();
let info = asio_channel_info(channel, is_input)?;
Ok(driver_name_to_utf8(&info.name).into_owned())

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 think this was already the case elsewhere with other names, but it's occurring to me that this will UB if there's ever a driver that doesn't NUL-terminate.

Comment thread src/host/asio/device.rs
.filter(|&r| driver.can_sample_rate(r.into()).unwrap_or(false))
.collect();

let input_channel_names: Box<[String]> = (0..channels.ins)

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.

We may want to check that the number of channels is greater than (or equal to) 0. I remember that ASIO often returns an i32 and we wouldn't want a negative value overflowing this.

channel_index: u16,
input: bool,
) -> Result<String, Error> {
let mut channel_name: *mut CFString = std::ptr::null_mut();

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.

As this CFString stuff is getting used more often, we could consider having a helper for it.

}

fn get_channel_name(&self, channel_index: u16, input: bool) -> Result<String, Error> {
if input && !self.supports_input() {

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.

supports_input/output aren't free, so if it's just to detail the error message then maybe we should just use the input argument but not re-query the device (or cache it, but that may be scope creep).

Comment thread src/host/asio/device.rs
input_sample_format: Option<SampleFormat>,
output_sample_format: Option<SampleFormat>,
supported_sample_rates: Box<[SampleRate]>,
input_channel_names: Box<[String]>,

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.

CoreAudio doesn't seem to cache this. What's the preferred approach? Lazily like CoreAudio or caching it during enumeration here?

@@ -943,6 +943,18 @@ impl Driver {
let mut dcb = DRIVER_EVENT_CALLBACKS.lock().unwrap();
dcb.retain(|&(id, _)| id != rem_id);

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.

cpal doesn't use get_ for accessors.

/// (`false`) direction.
///
/// The driver must already be loaded (i.e. this `Driver` instance must be alive).
pub fn channel_name(&self, channel: i32, is_input: bool) -> Result<String, AsioError> {

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.

Not sure about the input: bool or is_input: bool arguments in public functions. In the rest of cpal, that's split between supports_input/output, default_input/output_config, etc. That's more readable than channel_name(1, true) - what argument isn't self-explanatory.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants