From b9d27520b572e11c2a52d02ac4cbd017649edf40 Mon Sep 17 00:00:00 2001 From: Henrik Date: Sun, 20 Jul 2025 21:45:22 +0200 Subject: [PATCH 1/5] Include OSStatus when formatting the Unknown error --- src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index c62738c13..67da363f7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -328,7 +328,7 @@ impl ::std::fmt::Display for Error { Error::AudioCodec(ref err) => write!(f, "{}", err), Error::AudioFormat(ref err) => write!(f, "{}", err), Error::AudioUnit(ref err) => write!(f, "{}", err), - Error::Unknown(_) => write!(f, "An unknown error unknown to the coreaudio-rs API occurred"), + Error::Unknown(os_status) => write!(f, "An error unknown to the coreaudio-rs API occurred, OSStatus: {}", os_status), } } } From e5ed80ff259c58bdc7398c0203c1e35596a04569 Mon Sep 17 00:00:00 2001 From: Henrik Date: Mon, 21 Jul 2025 22:13:08 +0200 Subject: [PATCH 2/5] Mark unsafe functions, fix other clippy warnings --- src/audio_unit/macos_helpers.rs | 8 +++--- src/audio_unit/mod.rs | 46 +++++++++++++++++++------------ src/audio_unit/render_callback.rs | 6 ++-- src/audio_unit/stream_format.rs | 10 +++---- src/error.rs | 18 ++++++------ 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/audio_unit/macos_helpers.rs b/src/audio_unit/macos_helpers.rs index 948c43fd4..20184e03b 100644 --- a/src/audio_unit/macos_helpers.rs +++ b/src/audio_unit/macos_helpers.rs @@ -63,7 +63,7 @@ pub fn get_default_device_id(input: bool) -> Option { NonNull::from(&mut audio_device_id).cast(), ) }; - if status != kAudioHardwareNoError as i32 { + if status != kAudioHardwareNoError { return None; } @@ -248,7 +248,7 @@ pub fn get_audio_device_supports_scope(devid: AudioDeviceID, scope: Scope) -> Re NonNull::from(&data_size), NonNull::new(buffers).unwrap().cast(), ); - if status != kAudioHardwareNoError as i32 { + if status != kAudioHardwareNoError { return Err(Error::Unknown(status)); } @@ -333,7 +333,7 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result Error::from_os_status(status)?; let n_ranges = data_size as usize / mem::size_of::(); let mut ranges: Vec = vec![]; - ranges.reserve_exact(n_ranges as usize); + ranges.reserve_exact(n_ranges); ranges.set_len(n_ranges); let status = AudioObjectGetPropertyData( device_id, @@ -559,7 +559,7 @@ pub fn get_supported_physical_stream_formats( Error::from_os_status(status)?; let n_formats = data_size as usize / mem::size_of::(); let mut formats: Vec = vec![]; - formats.reserve_exact(n_formats as usize); + formats.reserve_exact(n_formats); formats.set_len(n_formats); let status = AudioObjectGetPropertyData( diff --git a/src/audio_unit/mod.rs b/src/audio_unit/mod.rs index b667a80fa..927731a4c 100644 --- a/src/audio_unit/mod.rs +++ b/src/audio_unit/mod.rs @@ -227,7 +227,7 @@ impl AudioUnit { elem: Element, maybe_data: Option<&T>, ) -> Result<(), Error> { - set_property(self.instance, id, scope, elem, maybe_data) + unsafe { set_property(self.instance, id, scope, elem, maybe_data) } } /// Gets the value of an **AudioUnit** property. @@ -241,7 +241,7 @@ impl AudioUnit { /// - **scope**: The audio unit scope for the property. /// - **elem**: The audio unit element for the property. pub fn get_property(&self, id: u32, scope: Scope, elem: Element) -> Result { - get_property(self.instance, id, scope, elem) + unsafe { get_property(self.instance, id, scope, elem) } } /// Starts an I/O **AudioUnit**, which in turn starts the audio unit processing graph that it is @@ -290,10 +290,10 @@ impl AudioUnit { /// > /// > - iOS input and output: Linear PCM with 16-bit integer samples. /// > - iOS audio units and other audio processing: Noninterleaved linear PCM with 8.24-bit - /// fixed-point samples + /// > fixed-point samples /// > - Mac input and output: Linear PCM with 32-bit floating point samples. /// > - Mac audio units and other audio processing: Noninterleaved linear PCM with 32-bit - /// floating-point + /// > floating-point pub fn set_stream_format( &mut self, stream_format: StreamFormat, @@ -375,7 +375,14 @@ impl Drop for AudioUnit { /// - **scope**: The audio unit scope for the property. /// - **elem**: The audio unit element for the property. /// - **maybe_data**: The value that you want to apply to the property. -pub fn set_property( +/// +/// Safety +/// ------ +/// This function is safe as long as the **au** parameter is a valid pointer to an AudioUnit instance. +/// The caller is responsible for ensuring this. +/// For a safer alternative, consider using an [AudioUnit] instance +/// and calling the associated [AudioUnit::set_property] method. +pub unsafe fn set_property( au: InnerAudioUnit, id: u32, scope: Scope, @@ -391,7 +398,7 @@ pub fn set_property( .unwrap_or_else(|| (::std::ptr::null(), 0)); let scope = scope as c_uint; let elem = elem as c_uint; - unsafe { try_os_status!(AudioUnitSetProperty(au, id, scope, elem, data_ptr, size)) } + try_os_status!(AudioUnitSetProperty(au, id, scope, elem, data_ptr, size)); Ok(()) } @@ -406,7 +413,14 @@ pub fn set_property( /// - **id**: The identifier of the property. /// - **scope**: The audio unit scope for the property. /// - **elem**: The audio unit element for the property. -pub fn get_property( +/// +/// Safety +/// ------ +/// This function is safe as long as the **au** parameter is a valid pointer to an AudioUnit instance. +/// The caller is responsible for ensuring this. +/// For a safer alternative, consider using an [AudioUnit] instance +/// and calling the associated [AudioUnit::get_property] method. +pub unsafe fn get_property( au: InnerAudioUnit, id: u32, scope: Scope, @@ -415,16 +429,14 @@ pub fn get_property( let scope = scope as c_uint; let elem = elem as c_uint; let mut size = ::std::mem::size_of::() as u32; - unsafe { - let mut data_uninit = ::std::mem::MaybeUninit::::uninit(); - let data_ptr = NonNull::from(&mut data_uninit).cast::(); - let size_ptr = NonNull::from(&mut size); - try_os_status!(AudioUnitGetProperty( - au, id, scope, elem, data_ptr, size_ptr - )); - let data: T = data_uninit.assume_init(); - Ok(data) - } + let mut data_uninit = ::std::mem::MaybeUninit::::uninit(); + let data_ptr = NonNull::from(&mut data_uninit).cast::(); + let size_ptr = NonNull::from(&mut size); + try_os_status!(AudioUnitGetProperty( + au, id, scope, elem, data_ptr, size_ptr + )); + let data: T = data_uninit.assume_init(); + Ok(data) } /// Gets the value of a specified audio session property. diff --git a/src/audio_unit/render_callback.rs b/src/audio_unit/render_callback.rs index 0f625bedf..00b3c3118 100644 --- a/src/audio_unit/render_callback.rs +++ b/src/audio_unit/render_callback.rs @@ -504,7 +504,7 @@ impl AudioUnit { data, time_stamp: in_time_stamp.read(), flags, - bus_number: in_bus_number as u32, + bus_number: in_bus_number, num_frames: in_number_frames as usize, } }; @@ -678,7 +678,7 @@ impl AudioUnit { data, time_stamp: in_time_stamp.read(), flags, - bus_number: in_bus_number as u32, + bus_number: in_bus_number, num_frames: in_number_frames as usize, } }; @@ -744,7 +744,7 @@ impl AudioUnit { // Take ownership over the AudioBufferList in order to safely free it. let buffer_list: Box = Box::from_raw(buffer_list); // Free the allocated data from the individual audio buffers. - let ptr = buffer_list.mBuffers.as_ptr() as *const AudioBuffer; + let ptr = buffer_list.mBuffers.as_ptr(); let len = buffer_list.mNumberBuffers as usize; let buffers: &[AudioBuffer] = slice::from_raw_parts(ptr, len); for &buffer in buffers { diff --git a/src/audio_unit/stream_format.rs b/src/audio_unit/stream_format.rs index 974fb8e05..7a41bdf19 100644 --- a/src/audio_unit/stream_format.rs +++ b/src/audio_unit/stream_format.rs @@ -23,7 +23,7 @@ use crate::error::{self, Error}; /// `bits_per_channel = size_of::()` / channels_per_frame * 8 /// /// > A *packet* is a collection of one or more contiguous frames. In linear PCM audio, a packet is -/// always a single frame. +/// > always a single frame. /// /// [from *Core Audio Overview*](https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/WhatisCoreAudio/WhatisCoreAudio.html) /// @@ -31,10 +31,10 @@ use crate::error::{self, Error}; /// > /// > - iOS input and output: Linear PCM with 16-bit integer samples. /// > - iOS audio units and other audio processing: Noninterleaved linear PCM with 8.24-bit -/// fixed-point samples +/// > fixed-point samples /// > - Mac input and output: Linear PCM with 32-bit floating point samples. /// > - Mac audio units and other audio processing: Noninterleaved linear PCM with 32-bit floating -/// point samples. +/// > point samples. #[derive(Copy, Clone, Debug)] pub struct StreamFormat { /// The number of frames of audio data per second used to represent a signal. @@ -61,7 +61,7 @@ impl StreamFormat { /// specified in the documentation: /// /// > Specify kAudioFormatLinearPCM for the mFormatID field. Audio units use uncompressed audio - /// data, so this is the correct format identifier to use whenever you work with audio units. + /// > data, so this is the correct format identifier to use whenever you work with audio units. /// /// [*Audio Unit Hosting Guide for iOS*](https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/AudioUnitHostingFundamentals/AudioUnitHostingFundamentals.html) /// @@ -118,7 +118,7 @@ impl StreamFormat { let (format, maybe_flag) = AudioFormat::LinearPCM(flags | LinearPcmFlags::IS_PACKED).as_format_and_flag(); - let flag = maybe_flag.unwrap_or(::std::u32::MAX - 2147483647); + let flag = maybe_flag.unwrap_or(u32::MAX - 2147483647); let non_interleaved = flags.contains(LinearPcmFlags::IS_NON_INTERLEAVED); let bytes_per_frame = if non_interleaved { diff --git a/src/error.rs b/src/error.rs index 67da363f7..486e5f3f6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -55,7 +55,7 @@ pub mod audio { Error::MemFull => "Memory full", Error::Unknown => "An unknown error occurred", }; - write!(f, "{}", description) + write!(f, "{description}") } } } @@ -109,7 +109,7 @@ pub mod audio_codec { Error::NotEnoughBufferSpace => "Not enough buffer space", Error::Unknown => "Unknown error occurred", }; - write!(f, "{}", description) + write!(f, "{description}") } } } @@ -156,7 +156,7 @@ pub mod audio_format { Error::UnknownFormat => "The specified data format is not a known format", Error::Unknown => "Unknown error occurred", }; - write!(f, "{}", description) + write!(f, "{description}") } } } @@ -239,7 +239,7 @@ pub mod audio_unit { Error::Unauthorized => "Unauthorized", Error::Unknown => "Unknown error occurred", }; - write!(f, "{}", description) + write!(f, "{description}") } } } @@ -324,11 +324,11 @@ impl ::std::fmt::Display for Error { Error::NonInterleavedInputOnlySupportsMono => write!(f, "In non-interleaved mode input only supports one channel"), Error::UnsupportedSampleRate => write!(f, "The requested sample rate is not available"), Error::UnsupportedStreamFormat => write!(f, "The requested stream format is not available"), - Error::Audio(ref err) => write!(f, "{}", err), - Error::AudioCodec(ref err) => write!(f, "{}", err), - Error::AudioFormat(ref err) => write!(f, "{}", err), - Error::AudioUnit(ref err) => write!(f, "{}", err), - Error::Unknown(os_status) => write!(f, "An error unknown to the coreaudio-rs API occurred, OSStatus: {}", os_status), + Error::Audio(ref err) => write!(f, "{err}"), + Error::AudioCodec(ref err) => write!(f, "{err}"), + Error::AudioFormat(ref err) => write!(f, "{err}"), + Error::AudioUnit(ref err) => write!(f, "{err}"), + Error::Unknown(os_status) => write!(f, "An error unknown to the coreaudio-rs API occurred, OSStatus: {os_status}"), } } } From be19cebd65bd792b580946eede11b1411fba05c7 Mon Sep 17 00:00:00 2001 From: Henrik Date: Mon, 21 Jul 2025 22:26:02 +0200 Subject: [PATCH 3/5] Unused import in example --- examples/sine_advanced.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/sine_advanced.rs b/examples/sine_advanced.rs index b2c6a2c29..ed33ce107 100644 --- a/examples/sine_advanced.rs +++ b/examples/sine_advanced.rs @@ -7,8 +7,11 @@ use coreaudio::audio_unit::audio_format::LinearPcmFlags; use coreaudio::audio_unit::macos_helpers::{ audio_unit_from_device_id, find_matching_physical_format, get_default_device_id, get_hogging_pid, get_supported_physical_stream_formats, set_device_physical_stream_format, - set_device_sample_rate, toggle_hog_mode, AliveListener, RateListener, + toggle_hog_mode, AliveListener, RateListener, }; +// This import is not needed since the use of set_device_sample_rate +// is commented out and left as an example. +// use coreaudio::audio_unit::macos_helpers::set_device_sample_rate; use coreaudio::audio_unit::render_callback::{self, data}; use coreaudio::audio_unit::{Element, SampleFormat, Scope, StreamFormat}; use objc2_audio_toolbox::kAudioUnitProperty_StreamFormat; From af14a822cd495c33c1b39e6b308b861ba5324507 Mon Sep 17 00:00:00 2001 From: Henrik Date: Thu, 24 Jul 2025 08:27:37 +0200 Subject: [PATCH 4/5] Add fmt and clippy to ci --- .github/workflows/coreaudio-rs.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/coreaudio-rs.yml b/.github/workflows/coreaudio-rs.yml index a8480238e..25b13adad 100644 --- a/.github/workflows/coreaudio-rs.yml +++ b/.github/workflows/coreaudio-rs.yml @@ -20,6 +20,28 @@ jobs: # - name: cargo test - all features # run: cargo test --all-features --verbose + macos-clippy: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: clippy + - name: cargo clippy + run: cargo clippy -- -D warnings + + macos-rustfmt: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - name: cargo fmt + run: cargo fmt --all -- --check + security-audit: runs-on: ubuntu-latest steps: From 4329671d5017b6b1af08eaa140abfbfaf27b2976 Mon Sep 17 00:00:00 2001 From: Henrik Date: Thu, 24 Jul 2025 08:33:03 +0200 Subject: [PATCH 5/5] Remove needless cast --- src/audio_unit/macos_helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio_unit/macos_helpers.rs b/src/audio_unit/macos_helpers.rs index 20184e03b..c29951c30 100644 --- a/src/audio_unit/macos_helpers.rs +++ b/src/audio_unit/macos_helpers.rs @@ -848,7 +848,7 @@ pub fn toggle_hog_mode(device_id: AudioDeviceID) -> Result { NonNull::from(&property_address), 0, null(), - data_size as u32, + data_size, NonNull::from(&temp_pid).cast(), ); Error::from_os_status(status)?;