From ba91b2b91c8385313a1bf4ea8ad9e1ae86588399 Mon Sep 17 00:00:00 2001 From: Andreas Pehrson Date: Fri, 31 May 2024 01:12:06 +0200 Subject: [PATCH] Return both a stream's id and its owning device id from get_device_streams This could be useful if a caller needs to filter something based on the owning device's properties, and is not possible to put outside of get_device_streams since it could get the streams from a sub device, in case streams were requested on an aggregate device. --- src/backend/device_property.rs | 31 +++++++++++++++++++++------- src/backend/mod.rs | 12 +++++------ src/backend/tests/device_property.rs | 28 ++++++++++++------------- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/backend/device_property.rs b/src/backend/device_property.rs index 255aef21..18dadefc 100644 --- a/src/backend/device_property.rs +++ b/src/backend/device_property.rs @@ -195,10 +195,15 @@ pub fn get_device_latency( } } +#[derive(Debug)] +pub struct DeviceStream { + pub device: AudioDeviceID, + pub stream: AudioStreamID, +} pub fn get_device_streams( id: AudioDeviceID, devtype: DeviceType, -) -> std::result::Result, OSStatus> { +) -> std::result::Result, OSStatus> { assert_ne!(id, kAudioObjectUnknown); debug_assert_running_serially(); @@ -210,12 +215,16 @@ pub fn get_device_streams( return Err(err); } - let mut streams: Vec = allocate_array_by_size(size); + let mut streams = vec![AudioObjectID::default(); size / mem::size_of::()]; let err = audio_object_get_property_data(id, &address, &mut size, streams.as_mut_ptr()); if err != NO_ERR { return Err(err); } + let mut device_streams = streams + .into_iter() + .map(|stream| DeviceStream { device: id, stream }) + .collect::>(); if devtype.contains(DeviceType::INPUT) { // With VPIO, output devices will/may get a Tap that appears as an input stream on the // output device id. It is unclear what kind of Tap this is as it cannot be enumerated @@ -251,26 +260,32 @@ pub fn get_device_streams( } debug_assert!(devices.contains(&id)); devices.sort(); - let next_id = devices.into_iter().skip_while(|&i| i != id).skip(1).next(); + let next_id = devices.into_iter().skip_while(|&i| i != id).nth(1); cubeb_log!( "Filtering input streams {:?} for device {}. Next device is {:?}.", - streams, + device_streams + .iter() + .map(|ds| ds.stream) + .collect::>(), id, next_id ); if let Some(next_id) = next_id { - streams.retain(|&s| s > id && s < next_id); + device_streams.retain(|ds| ds.stream > id && ds.stream < next_id); } else { - streams.retain(|&s| s > id); + device_streams.retain(|ds| ds.stream > id); } cubeb_log!( "Input stream filtering for device {} retained {:?}.", id, - streams + device_streams + .iter() + .map(|ds| ds.stream) + .collect::>() ); } - Ok(streams) + Ok(device_streams) } pub fn get_device_sample_rate( diff --git a/src/backend/mod.rs b/src/backend/mod.rs index d81bdbbb..79354774 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1620,10 +1620,10 @@ fn get_channel_count( assert_ne!(devid, kAudioObjectUnknown); debug_assert_running_serially(); - let streams = get_device_streams(devid, devtype)?; + let devstreams = get_device_streams(devid, devtype)?; let mut count = 0; - for stream in streams { - if let Ok(format) = get_stream_virtual_format(stream) { + for ds in devstreams { + if let Ok(format) = get_stream_virtual_format(ds.stream) { count += format.mChannelsPerFrame; } } @@ -1670,8 +1670,8 @@ fn get_fixed_latency(devid: AudioObjectID, devtype: DeviceType) -> u32 { } }; - let stream_latency = get_device_streams(devid, devtype).and_then(|streams| { - if streams.is_empty() { + let stream_latency = get_device_streams(devid, devtype).and_then(|devstreams| { + if devstreams.is_empty() { cubeb_log!( "No stream on device {} in {:?} scope!", devid, @@ -1679,7 +1679,7 @@ fn get_fixed_latency(devid: AudioObjectID, devtype: DeviceType) -> u32 { ); Ok(0) // default stream latency } else { - get_stream_latency(streams[0]) + get_stream_latency(devstreams[0].stream) } }).map_err(|e| { cubeb_log!( diff --git a/src/backend/tests/device_property.rs b/src/backend/tests/device_property.rs index 3fd192b2..15eeb2a2 100644 --- a/src/backend/tests/device_property.rs +++ b/src/backend/tests/device_property.rs @@ -413,20 +413,20 @@ fn test_get_ranges_of_device_sample_rate_by_unknown_device() { #[test] fn test_get_stream_latency() { if let Some(device) = test_get_default_device(Scope::Input) { - let streams = run_serially(|| get_device_streams(device, DeviceType::INPUT)).unwrap(); - for stream in streams { - let latency = run_serially(|| get_stream_latency(stream)).unwrap(); - println!("latency of the input stream {} is {}", stream, latency); + let devstreams = run_serially(|| get_device_streams(device, DeviceType::INPUT)).unwrap(); + for ds in devstreams { + let latency = run_serially(|| get_stream_latency(ds.stream)).unwrap(); + println!("latency of the input stream {} is {}", ds.stream, latency); } } else { println!("No input device."); } if let Some(device) = test_get_default_device(Scope::Output) { - let streams = run_serially(|| get_device_streams(device, DeviceType::OUTPUT)).unwrap(); - for stream in streams { - let latency = run_serially(|| get_stream_latency(stream)).unwrap(); - println!("latency of the output stream {} is {}", stream, latency); + let devstreams = run_serially(|| get_device_streams(device, DeviceType::OUTPUT)).unwrap(); + for ds in devstreams { + let latency = run_serially(|| get_stream_latency(ds.stream)).unwrap(); + println!("latency of the output stream {} is {}", ds.stream, latency); } } else { println!("No output device."); @@ -444,10 +444,10 @@ fn test_get_stream_latency_by_unknown_device() { #[test] fn test_get_stream_virtual_format() { if let Some(device) = test_get_default_device(Scope::Input) { - let streams = run_serially(|| get_device_streams(device, DeviceType::INPUT)).unwrap(); - let formats = streams + let devstreams = run_serially(|| get_device_streams(device, DeviceType::INPUT)).unwrap(); + let formats = devstreams .iter() - .map(|s| run_serially(|| get_stream_virtual_format(*s))) + .map(|ds| run_serially(|| get_stream_virtual_format(ds.stream))) .collect::>>(); println!("input stream formats: {:?}", formats); assert!(!formats.is_empty()); @@ -456,10 +456,10 @@ fn test_get_stream_virtual_format() { } if let Some(device) = test_get_default_device(Scope::Output) { - let streams = run_serially(|| get_device_streams(device, DeviceType::OUTPUT)).unwrap(); - let formats = streams + let devstreams = run_serially(|| get_device_streams(device, DeviceType::OUTPUT)).unwrap(); + let formats = devstreams .iter() - .map(|s| run_serially(|| get_stream_virtual_format(*s))) + .map(|ds| run_serially(|| get_stream_virtual_format(ds.stream))) .collect::>>(); println!("output stream formats: {:?}", formats); assert!(!formats.is_empty());