diff --git a/Cargo.toml b/Cargo.toml index bfa913844..93f3e6b49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "coreaudio-rs" version = "0.12.1" -authors = ["mitchmindtree ", "yupferris "] +authors = [ + "mitchmindtree ", + "yupferris ", +] description = "A friendly rust interface for Apple's CoreAudio API." keywords = ["core", "audio", "unit", "osx", "ios"] readme = "README.md" @@ -14,19 +17,98 @@ homepage = "https://github.com/RustAudio/coreaudio-rs" name = "coreaudio" [features] -default = ["audio_toolbox", "audio_unit", "core_audio", "open_al", "core_midi"] -audio_toolbox = ["coreaudio-sys/audio_toolbox"] -audio_unit = ["coreaudio-sys/audio_unit"] -core_audio = ["coreaudio-sys/core_audio"] -open_al = ["coreaudio-sys/open_al"] -core_midi = ["coreaudio-sys/core_midi"] +default = ["audio_toolbox", "core_audio"] +audio_toolbox = ["dep:objc2-audio-toolbox", "dep:objc2-core-foundation"] +core_audio = ["dep:objc2-core-audio", "dep:objc2-core-audio-types"] +core_midi = ["dep:objc2-core-midi"] + +# Deprecated +audio_unit = ["audio_toolbox"] + +# Unsupported +open_al = [] [dependencies] bitflags = "1.0" -coreaudio-sys = { version = "0.2", default-features = false } -core-foundation-sys = "0.8.3" +libc = "0.2" +objc2-core-foundation = { version = "0.3", optional = true, default-features = false, features = [ + "std", + "CFBase", + "CFString", +] } +objc2-audio-toolbox = { version = "0.3", optional = true, default-features = false, features = [ + "std", + "bitflags", + "libc", + "objc2-core-foundation", + "AUAudioUnit", + "AUAudioUnitImplementation", + "AUCocoaUIView", + "AUComponent", + "AUGraph", + "AUParameters", + "AudioCodec", + "AudioComponent", + "AudioConverter", + "AudioFile", + "AudioFileStream", + "AudioFormat", + "AudioOutputUnit", + "AudioQueue", + "AudioServices", + "AudioSession", + "AudioUnit", + "AudioUnitCarbonView", + "AudioUnitParameters", + "AudioUnitProperties", + "AudioUnitUtilities", + "AudioWorkInterval", + "CAFFile", + "CAShow", + "DefaultAudioOutput", + "ExtendedAudioFile", + "MusicDevice", + "MusicPlayer", + "objc2-core-audio", + "objc2-core-audio-types", +] } +objc2-core-audio = { version = "0.3", optional = true, default-features = false, features = [ + "std", + "objc2-core-audio-types", + "AudioHardware", + "AudioHardwareDeprecated", + "AudioServerPlugIn", + "HostTime", +] } +objc2-core-audio-types = { version = "0.3", optional = true, default-features = false, features = [ + "std", + "bitflags", + "AudioSessionTypes", + "CoreAudioBaseTypes", +] } +objc2-core-midi = { version = "0.3", optional = true, default-features = false, features = [ + "std", + "objc2-core-foundation", + "MIDIBluetoothConnection", + "MIDICIDevice", + "MIDICIDeviceManager", + "MIDICapabilityInquiry", + "MIDIDriver", + "MIDIMessages", + "MIDINetworkSession", + "MIDIServices", + "MIDISetup", + "MIDIThruConnection", + "MIDIUMPCI", + "MIDIUMPCIProfile", + "MIDIUMPEndpoint", + "MIDIUMPEndpointManager", + "MIDIUMPFunctionBlock", + "MIDIUMPMutableEndpoint", + "MIDIUMPMutableFunctionBlock", +] } [package.metadata.docs.rs] all-features = true -default-target = "x86_64-apple-darwin" -targets = ["x86_64-apple-darwin", "x86_64-apple-ios"] +default-target = "aarch64-apple-darwin" +targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-apple-ios"] diff --git a/src/audio_unit/macos_helpers.rs b/src/audio_unit/macos_helpers.rs index 9fbf4278a..8a08fbd52 100644 --- a/src/audio_unit/macos_helpers.rs +++ b/src/audio_unit/macos_helpers.rs @@ -1,20 +1,16 @@ -/// This is a collection of helper functions for performing common tasks on macOS. -/// These functions are only implemented for macOS, not iOS. +#![allow(deprecated)] +//! This is a collection of helper functions for performing common tasks on macOS. +//! These functions are only implemented for macOS, not iOS. use crate::error::Error; use std::collections::VecDeque; -use std::ffi::CStr; -use std::os::raw::{c_char, c_void}; -use std::ptr::null; +use std::ptr::{null, NonNull}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{channel, Sender}; use std::sync::Mutex; use std::time::Duration; use std::{mem, thread}; -use core_foundation_sys::string::{CFStringGetCString, CFStringGetCStringPtr, CFStringRef}; -use sys; -use sys::pid_t; -use sys::{ +use crate::sys::{ kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceIsAlive, kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyHogMode, kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, @@ -25,17 +21,20 @@ use sys::{ kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput, kAudioObjectSystemObject, kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO, kAudioStreamPropertyAvailablePhysicalFormats, kAudioStreamPropertyPhysicalFormat, - kCFStringEncodingUTF8, AudioDeviceID, AudioObjectAddPropertyListener, - AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize, AudioObjectID, - AudioObjectPropertyAddress, AudioObjectPropertyScope, AudioObjectRemovePropertyListener, - AudioObjectSetPropertyData, AudioStreamBasicDescription, AudioStreamRangedDescription, - AudioValueRange, OSStatus, + AudioDeviceID, AudioObjectAddPropertyListener, AudioObjectGetPropertyData, + AudioObjectGetPropertyDataSize, AudioObjectID, AudioObjectPropertyAddress, + AudioObjectPropertyScope, AudioObjectRemovePropertyListener, AudioObjectSetPropertyData, + AudioStreamBasicDescription, AudioStreamRangedDescription, AudioValueRange, OSStatus, }; +use libc::pid_t; +use objc2_core_audio::AudioObjectPropertyListenerProc; +use objc2_core_foundation::CFString; use crate::audio_unit::audio_format::{AudioFormat, LinearPcmFlags}; use crate::audio_unit::sample_format::SampleFormat; use crate::audio_unit::stream_format::StreamFormat; use crate::audio_unit::{AudioUnit, Element, IOType, Scope}; +use crate::sys; /// Helper function to get the device id of the default input or output device. pub fn get_default_device_id(input: bool) -> Option { @@ -50,16 +49,16 @@ pub fn get_default_device_id(input: bool) -> Option { mElement: kAudioObjectPropertyElementMaster, }; - let audio_device_id: AudioDeviceID = 0; - let data_size = mem::size_of::(); + let mut audio_device_id: AudioDeviceID = 0; + let data_size = mem::size_of::() as u32; let status = unsafe { AudioObjectGetPropertyData( - kAudioObjectSystemObject, - &property_address as *const _, + kAudioObjectSystemObject as AudioObjectID, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &audio_device_id as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut audio_device_id).cast(), ) }; if status != kAudioHardwareNoError as i32 { @@ -79,7 +78,10 @@ pub fn get_device_id_from_name(name: &str, input: bool) -> Option if let Ok(all_ids) = get_audio_device_ids() { return all_ids .iter() - .find(|id| get_device_name(**id).unwrap_or_default() == name && get_audio_device_supports_scope(**id, scope).unwrap_or_default()) + .find(|id| { + get_device_name(**id).unwrap_or_default() == name + && get_audio_device_supports_scope(**id, scope).unwrap_or_default() + }) .copied(); } None @@ -144,14 +146,14 @@ pub fn get_audio_device_ids_for_scope(scope: Scope) -> Result }; } - let data_size = 0u32; + let mut data_size = 0u32; let status = unsafe { AudioObjectGetPropertyDataSize( - kAudioObjectSystemObject, - &property_address as *const _, + kAudioObjectSystemObject as AudioObjectID, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&mut data_size), ) }; try_status_or_return!(status); @@ -163,12 +165,12 @@ pub fn get_audio_device_ids_for_scope(scope: Scope) -> Result let status = unsafe { AudioObjectGetPropertyData( - kAudioObjectSystemObject, - &property_address as *const _, + kAudioObjectSystemObject as AudioObjectID, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - audio_devices.as_mut_ptr() as *mut _, + NonNull::from(&data_size), + NonNull::new(audio_devices.as_mut_ptr()).unwrap().cast(), ) }; try_status_or_return!(status); @@ -221,14 +223,14 @@ pub fn get_audio_device_supports_scope(devid: AudioDeviceID, scope: Scope) -> Re }; } - let data_size = 0u32; + let mut data_size = 0u32; let status = unsafe { AudioObjectGetPropertyDataSize( devid, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&mut data_size), ) }; try_status_or_return!(status); @@ -238,11 +240,11 @@ pub fn get_audio_device_supports_scope(devid: AudioDeviceID, scope: Scope) -> Re unsafe { let status = AudioObjectGetPropertyData( devid, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - buffers as *mut _, + NonNull::from(&data_size), + NonNull::new(buffers).unwrap().cast(), ); if status != kAudioHardwareNoError as i32 { return Err(Error::Unknown(status)); @@ -274,46 +276,21 @@ pub fn get_device_name(device_id: AudioDeviceID) -> Result { }; } - let device_name: CFStringRef = null(); - let data_size = mem::size_of::(); - let c_str = unsafe { + let mut device_name: *const CFString = null(); + let data_size = mem::size_of::<*const CFString>() as u32; + unsafe { let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &device_name as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut device_name).cast(), ); try_status_or_return!(status); - let c_string: *const c_char = CFStringGetCStringPtr(device_name, kCFStringEncodingUTF8); - if c_string.is_null() { - let status = AudioObjectGetPropertyData( - device_id, - &property_address as *const _, - 0, - null(), - &data_size as *const _ as *mut _, - &device_name as *const _ as *mut _, - ); - try_status_or_return!(status); - let mut buf: [i8; 255] = [0; 255]; - let result = CFStringGetCString( - device_name, - buf.as_mut_ptr(), - buf.len() as _, - kCFStringEncodingUTF8, - ); - if result == 0 { - return Err(Error::Unknown(result as i32)); - } - let name: &CStr = CStr::from_ptr(buf.as_ptr()); - return Ok(name.to_str().unwrap().to_owned()); - } - CStr::from_ptr(c_string as *mut _) - }; - Ok(c_str.to_string_lossy().into_owned()) + Ok((&*device_name).to_string()) + } } /// Change the sample rate of a device. @@ -327,15 +304,15 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster, }; - let sample_rate: f64 = 0.0; + let mut sample_rate: f64 = 0.0; let data_size = mem::size_of::() as u32; let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &sample_rate as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut sample_rate).cast(), ); Error::from_os_status(status)?; @@ -343,13 +320,13 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result if sample_rate as u32 != new_rate as u32 { // Get available sample rate ranges. property_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; - let data_size = 0u32; + let mut data_size = 0u32; let status = AudioObjectGetPropertyDataSize( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&mut data_size), ); Error::from_os_status(status)?; let n_ranges = data_size as usize / mem::size_of::(); @@ -358,11 +335,11 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result ranges.set_len(n_ranges); let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - ranges.as_mut_ptr() as *mut _, + NonNull::from(&data_size), + NonNull::new(ranges.as_mut_ptr()).unwrap().cast(), ); Error::from_os_status(status)?; @@ -388,11 +365,11 @@ pub fn set_device_sample_rate(device_id: AudioDeviceID, new_rate: f64) -> Result // Finally, set the sample rate. let status = AudioObjectSetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), data_size, - &ranges[range_index] as *const _ as *const _, + NonNull::from(&ranges[range_index]).cast(), ); Error::from_os_status(status)?; @@ -481,15 +458,16 @@ pub fn set_device_physical_stream_format( mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster, }; - let maybe_asbd: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + let mut maybe_asbd: mem::MaybeUninit = + mem::MaybeUninit::zeroed(); let data_size = mem::size_of::() as u32; let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &maybe_asbd as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut maybe_asbd).cast(), ); Error::from_os_status(status)?; let asbd = maybe_asbd.assume_init(); @@ -503,15 +481,15 @@ pub fn set_device_physical_stream_format( let reported_asbd: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - let reported_asbd = reported_asbd.assume_init(); + let mut reported_asbd = reported_asbd.assume_init(); let status = AudioObjectSetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), data_size, - &new_asbd as *const _ as *const _, + NonNull::from(&new_asbd).cast(), ); Error::from_os_status(status)?; @@ -521,11 +499,11 @@ pub fn set_device_physical_stream_format( loop { let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &reported_asbd as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut reported_asbd).cast(), ); Error::from_os_status(status)?; if asbds_are_equal(&reported_asbd, &new_asbd) { @@ -571,10 +549,10 @@ pub fn get_supported_physical_stream_formats( let mut data_size = 0u32; let status = AudioObjectGetPropertyDataSize( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &mut data_size as *mut _, + NonNull::from(&mut data_size), ); Error::from_os_status(status)?; let n_formats = data_size as usize / mem::size_of::(); @@ -584,11 +562,11 @@ pub fn get_supported_physical_stream_formats( let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - formats.as_mut_ptr() as *mut _, + NonNull::from(&data_size), + NonNull::new(formats.as_mut_ptr()).unwrap().cast(), ); Error::from_os_status(status)?; formats @@ -603,9 +581,7 @@ pub struct RateListener { sync_channel: Option>, device_id: AudioDeviceID, property_address: AudioObjectPropertyAddress, - rate_listener: Option< - unsafe extern "C" fn(u32, u32, *const AudioObjectPropertyAddress, *mut c_void) -> i32, - >, + rate_listener: AudioObjectPropertyListenerProc, } impl Drop for RateListener { @@ -638,15 +614,15 @@ impl RateListener { /// Register this listener to receive notifications. pub fn register(&mut self) -> Result<(), Error> { - unsafe extern "C" fn rate_listener( + unsafe extern "C-unwind" fn rate_listener( device_id: AudioObjectID, _n_addresses: u32, - _properties: *const AudioObjectPropertyAddress, + _properties: NonNull, self_ptr: *mut ::std::os::raw::c_void, ) -> OSStatus { let self_ptr: &mut RateListener = &mut *(self_ptr as *mut RateListener); - let rate: f64 = 0.0; - let data_size = mem::size_of::(); + let mut rate: f64 = 0.0; + let data_size = mem::size_of::() as u32; let property_address = AudioObjectPropertyAddress { mSelector: kAudioDevicePropertyNominalSampleRate, mScope: kAudioObjectPropertyScopeGlobal, @@ -654,11 +630,11 @@ impl RateListener { }; let result = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &rate as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut rate).cast(), ); if let Some(sender) = &self_ptr.sync_channel { sender.send(rate).unwrap(); @@ -673,7 +649,7 @@ impl RateListener { let status = unsafe { AudioObjectAddPropertyListener( self.device_id, - &self.property_address as *const _, + NonNull::from(&self.property_address), Some(rate_listener), self as *const _ as *mut _, ) @@ -689,7 +665,7 @@ impl RateListener { let status = unsafe { AudioObjectRemovePropertyListener( self.device_id, - &self.property_address as *const _, + NonNull::from(&self.property_address), self.rate_listener, self as *const _ as *mut _, ) @@ -731,9 +707,7 @@ pub struct AliveListener { alive: Box, device_id: AudioDeviceID, property_address: AudioObjectPropertyAddress, - alive_listener: Option< - unsafe extern "C" fn(u32, u32, *const AudioObjectPropertyAddress, *mut c_void) -> i32, - >, + alive_listener: AudioObjectPropertyListenerProc, } impl Drop for AliveListener { @@ -762,15 +736,15 @@ impl AliveListener { /// Register this listener to receive notifications. pub fn register(&mut self) -> Result<(), Error> { - unsafe extern "C" fn alive_listener( + unsafe extern "C-unwind" fn alive_listener( device_id: AudioObjectID, _n_addresses: u32, - _properties: *const AudioObjectPropertyAddress, + _properties: NonNull, self_ptr: *mut ::std::os::raw::c_void, ) -> OSStatus { let self_ptr: &mut AliveListener = &mut *(self_ptr as *mut AliveListener); - let alive: u32 = 0; - let data_size = mem::size_of::(); + let mut alive: u32 = 0; + let data_size = mem::size_of::() as u32; let property_address = AudioObjectPropertyAddress { mSelector: kAudioDevicePropertyDeviceIsAlive, mScope: kAudioObjectPropertyScopeGlobal, @@ -778,11 +752,11 @@ impl AliveListener { }; let result = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &alive as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut alive).cast(), ); self_ptr.alive.store(alive > 0, Ordering::SeqCst); result @@ -792,7 +766,7 @@ impl AliveListener { let status = unsafe { AudioObjectAddPropertyListener( self.device_id, - &self.property_address as *const _, + NonNull::from(&self.property_address), Some(alive_listener), self as *const _ as *mut _, ) @@ -808,7 +782,7 @@ impl AliveListener { let status = unsafe { AudioObjectRemovePropertyListener( self.device_id, - &self.property_address as *const _, + NonNull::from(&self.property_address), self.alive_listener, self as *const _ as *mut _, ) @@ -835,15 +809,15 @@ pub fn get_hogging_pid(device_id: AudioDeviceID) -> Result { mElement: kAudioObjectPropertyElementMaster, }; let pid = unsafe { - let temp_pid: pid_t = 0; - let data_size = mem::size_of::(); + let mut temp_pid: pid_t = 0; + let data_size = mem::size_of::() as u32; let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &temp_pid as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut temp_pid).cast(), ); Error::from_os_status(status)?; temp_pid @@ -865,24 +839,24 @@ pub fn toggle_hog_mode(device_id: AudioDeviceID) -> Result { mElement: kAudioObjectPropertyElementMaster, }; let pid = unsafe { - let temp_pid: pid_t = -1; - let data_size = mem::size_of::(); + let mut temp_pid: pid_t = -1; + let data_size = mem::size_of::() as u32; let status = AudioObjectSetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), data_size as u32, - &temp_pid as *const _ as *mut _, + NonNull::from(&temp_pid).cast(), ); Error::from_os_status(status)?; let status = AudioObjectGetPropertyData( device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &temp_pid as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut temp_pid).cast(), ); Error::from_os_status(status)?; temp_pid diff --git a/src/audio_unit/mod.rs b/src/audio_unit/mod.rs index 4f813c7f9..48f698114 100644 --- a/src/audio_unit/mod.rs +++ b/src/audio_unit/mod.rs @@ -19,11 +19,10 @@ //! fixes! use crate::error::Error; +use crate::sys; use std::mem; use std::os::raw::{c_uint, c_void}; -use std::ptr; - -use sys; +use std::ptr::{self, NonNull}; pub use self::audio_format::AudioFormat; pub use self::sample_format::{Sample, SampleFormat}; @@ -145,7 +144,7 @@ impl AudioUnit { // find the first system audio unit matching the description, using a system-defined // ordering. If you instead pass a previously found audio unit reference in this // parameter, the function locates the next audio unit matching the description. - let component = sys::AudioComponentFindNext(ptr::null_mut(), &desc as *const _); + let component = sys::AudioComponentFindNext(ptr::null_mut(), NonNull::from(&desc)); if component.is_null() { return Err(Error::NoMatchingDefaultAudioUnitFound); } @@ -154,7 +153,7 @@ impl AudioUnit { let mut instance_uninit = mem::MaybeUninit::::uninit(); try_os_status!(sys::AudioComponentInstanceNew( component, - instance_uninit.as_mut_ptr() as *mut sys::AudioUnit + NonNull::from(&mut instance_uninit).cast() )); let instance: sys::AudioUnit = instance_uninit.assume_init(); @@ -413,8 +412,8 @@ pub fn get_property( let mut size = ::std::mem::size_of::() as u32; unsafe { let mut data_uninit = ::std::mem::MaybeUninit::::uninit(); - let data_ptr = data_uninit.as_mut_ptr() as *mut _ as *mut c_void; - let size_ptr = &mut size as *mut _; + let data_ptr = NonNull::from(&mut data_uninit).cast::(); + let size_ptr = NonNull::from(&mut size); try_os_status!(sys::AudioUnitGetProperty( au, id, scope, elem, data_ptr, size_ptr )); @@ -434,6 +433,7 @@ pub fn get_property( #[cfg(target_os = "ios")] pub fn audio_session_get_property(id: u32) -> Result { let mut size = ::std::mem::size_of::() as u32; + #[allow(deprecated)] unsafe { let mut data_uninit = ::std::mem::MaybeUninit::::uninit(); let data_ptr = data_uninit.as_mut_ptr() as *mut _ as *mut c_void; diff --git a/src/audio_unit/render_callback.rs b/src/audio_unit/render_callback.rs index 3d54c3358..7c21d1492 100644 --- a/src/audio_unit/render_callback.rs +++ b/src/audio_unit/render_callback.rs @@ -1,10 +1,11 @@ use super::audio_format::LinearPcmFlags; use super::{AudioUnit, Element, Scope}; use crate::error::{self, Error}; +use crate::sys; use std::mem; use std::os::raw::c_void; +use std::ptr::NonNull; use std::slice; -use sys; pub use self::action_flags::ActionFlags; pub use self::data::Data; @@ -15,10 +16,10 @@ pub use self::data::Data; /// This allows the user to provide a custom, more rust-esque callback function type that takes /// greater advantage of rust's type safety. pub type InputProcFn = dyn FnMut( - *mut sys::AudioUnitRenderActionFlags, - *const sys::AudioTimeStamp, - sys::UInt32, - sys::UInt32, + NonNull, + NonNull, + u32, + u32, *mut sys::AudioBufferList, ) -> sys::OSStatus; @@ -52,9 +53,9 @@ pub mod data { use super::super::Sample; use super::super::StreamFormat; use crate::audio_unit::audio_format::LinearPcmFlags; + use crate::sys; use std::marker::PhantomData; use std::slice; - use sys; /// Audio data wrappers specific to the `AudioUnit`'s `AudioFormat`. pub trait Data { @@ -291,8 +292,8 @@ pub mod data { } pub mod action_flags { + use crate::sys; use std::fmt; - use sys; bitflags! { pub struct ActionFlags: u32 { @@ -301,20 +302,20 @@ pub mod action_flags { /// before the render operation is performed. /// /// **Available** in OS X v10.0 and later. - const PRE_RENDER = sys::kAudioUnitRenderAction_PreRender; + const PRE_RENDER = sys::AudioUnitRenderActionFlags::UnitRenderAction_PreRender.0; /// Called on a render notification Proc, which is called either before or after the /// render operation of the audio unit. If this flag is set, the proc is being called /// after the render operation is completed. /// /// **Available** in OS X v10.0 and later. - const POST_RENDER = sys::kAudioUnitRenderAction_PostRender; + const POST_RENDER = sys::AudioUnitRenderActionFlags::UnitRenderAction_PostRender.0; /// This flag can be set in a render input callback (or in the audio unit's render /// operation itself) and is used to indicate that the render buffer contains only /// silence. It can then be used by the caller as a hint to whether the buffer needs to /// be processed or not. /// /// **Available** in OS X v10.2 and later. - const OUTPUT_IS_SILENCE = sys::kAudioUnitRenderAction_OutputIsSilence; + const OUTPUT_IS_SILENCE = sys::AudioUnitRenderActionFlags::UnitRenderAction_OutputIsSilence.0; /// This is used with offline audio units (of type 'auol'). It is used when an offline /// unit is being preflighted, which is performed prior to when the actual offline /// rendering actions are performed. It is used for those cases where the offline @@ -323,32 +324,32 @@ pub mod action_flags { /// normalization). /// /// **Available** in OS X v10.3 and later. - const OFFLINE_PREFLIGHT = sys::kAudioOfflineUnitRenderAction_Preflight; + const OFFLINE_PREFLIGHT = sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Preflight.0; /// Once an offline unit has been successfully preflighted, it is then put into its /// render mode. This flag is set to indicate to the audio unit that it is now in that /// state and that it should perform processing on the input data. /// /// **Available** in OS X v10.3 and later. - const OFFLINE_RENDER = sys::kAudioOfflineUnitRenderAction_Render; + const OFFLINE_RENDER = sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Render.0; /// This flag is set when an offline unit has completed either its preflight or /// performed render operation. /// /// **Available** in OS X v10.3 and later. - const OFFLINE_COMPLETE = sys::kAudioOfflineUnitRenderAction_Complete; + const OFFLINE_COMPLETE = sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Complete.0; /// If this flag is set on the post-render call an error was returned by the audio /// unit's render operation. In this case, the error can be retrieved through the /// `lastRenderError` property and the audio data in `ioData` handed to the post-render /// notification will be invalid. /// /// **Available** in OS X v10.5 and later. - const POST_RENDER_ERROR = sys::kAudioUnitRenderAction_PostRenderError; + const POST_RENDER_ERROR = sys::AudioUnitRenderActionFlags::UnitRenderAction_PostRenderError.0; /// If this flag is set, then checks that are done on the arguments provided to render /// are not performed. This can be useful to use to save computation time in situations /// where you are sure you are providing the correct arguments and structures to the /// various render calls. /// /// **Available** in OS X v10.7 and later. - const DO_NOT_CHECK_RENDER_ARGS = sys::kAudioUnitRenderAction_DoNotCheckRenderArgs; + const DO_NOT_CHECK_RENDER_ARGS = sys::AudioUnitRenderActionFlags::UnitRenderAction_DoNotCheckRenderArgs.0; } } @@ -376,11 +377,11 @@ pub mod action_flags { impl Handle { /// Retrieve the current state of the `ActionFlags`. pub fn get(&self) -> ActionFlags { - ActionFlags::from_bits_truncate(unsafe { *self.ptr }) + ActionFlags::from_bits_truncate(unsafe { *self.ptr }.0) } fn set(&mut self, flags: ActionFlags) { - unsafe { *self.ptr = flags.bits() } + unsafe { (*self.ptr).0 = flags.bits() } } /// The raw value of the flags currently stored. @@ -442,15 +443,21 @@ pub mod action_flags { write!( f, "{:?}", - match self.bits() { - sys::kAudioUnitRenderAction_PreRender => "PRE_RENDER", - sys::kAudioUnitRenderAction_PostRender => "POST_RENDER", - sys::kAudioUnitRenderAction_OutputIsSilence => "OUTPUT_IS_SILENCE", - sys::kAudioOfflineUnitRenderAction_Preflight => "OFFLINE_PREFLIGHT", - sys::kAudioOfflineUnitRenderAction_Render => "OFFLINE_RENDER", - sys::kAudioOfflineUnitRenderAction_Complete => "OFFLINE_COMPLETE", - sys::kAudioUnitRenderAction_PostRenderError => "POST_RENDER_ERROR", - sys::kAudioUnitRenderAction_DoNotCheckRenderArgs => "DO_NOT_CHECK_RENDER_ARGS", + match sys::AudioUnitRenderActionFlags(self.bits()) { + sys::AudioUnitRenderActionFlags::UnitRenderAction_PreRender => "PRE_RENDER", + sys::AudioUnitRenderActionFlags::UnitRenderAction_PostRender => "POST_RENDER", + sys::AudioUnitRenderActionFlags::UnitRenderAction_OutputIsSilence => + "OUTPUT_IS_SILENCE", + sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Preflight => + "OFFLINE_PREFLIGHT", + sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Render => + "OFFLINE_RENDER", + sys::AudioUnitRenderActionFlags::OfflineUnitRenderAction_Complete => + "OFFLINE_COMPLETE", + sys::AudioUnitRenderActionFlags::UnitRenderAction_PostRenderError => + "POST_RENDER_ERROR", + sys::AudioUnitRenderActionFlags::UnitRenderAction_DoNotCheckRenderArgs => + "DO_NOT_CHECK_RENDER_ARGS", _ => "", } ) @@ -479,18 +486,18 @@ impl AudioUnit { // // This allows us to take advantage of rust's type system and provide format-specific // `Args` types which can be checked at compile time. - let input_proc_fn = move |io_action_flags: *mut sys::AudioUnitRenderActionFlags, - in_time_stamp: *const sys::AudioTimeStamp, - in_bus_number: sys::UInt32, - in_number_frames: sys::UInt32, + let input_proc_fn = move |io_action_flags: NonNull, + in_time_stamp: NonNull, + in_bus_number: u32, + in_number_frames: u32, io_data: *mut sys::AudioBufferList| -> sys::OSStatus { let args = unsafe { let data = D::from_input_proc_args(in_number_frames, io_data); - let flags = action_flags::Handle::from_ptr(io_action_flags); + let flags = action_flags::Handle::from_ptr(io_action_flags.as_ptr()); Args { data, - time_stamp: *in_time_stamp, + time_stamp: in_time_stamp.read(), flags, bus_number: in_bus_number as u32, num_frames: in_number_frames as usize, @@ -600,10 +607,10 @@ impl AudioUnit { // This allows us to take advantage of rust's type system and provide format-specific // `Args` types which can be checked at compile time. let audio_unit = self.instance; - let input_proc_fn = move |io_action_flags: *mut sys::AudioUnitRenderActionFlags, - in_time_stamp: *const sys::AudioTimeStamp, - in_bus_number: sys::UInt32, - in_number_frames: sys::UInt32, + let input_proc_fn = move |io_action_flags: NonNull, + in_time_stamp: NonNull, + in_bus_number: u32, + in_number_frames: u32, _io_data: *mut sys::AudioBufferList| -> sys::OSStatus { // If the buffer size has changed, ensure the AudioBuffer is the correct size. @@ -648,11 +655,11 @@ impl AudioUnit { unsafe { let status = sys::AudioUnitRender( audio_unit, - io_action_flags, + io_action_flags.as_ptr(), in_time_stamp, in_bus_number, in_number_frames, - audio_buffer_list_ptr, + NonNull::new(audio_buffer_list_ptr).unwrap(), ); if status != 0 { return status; @@ -661,10 +668,10 @@ impl AudioUnit { let args = unsafe { let data = D::from_input_proc_args(in_number_frames, audio_buffer_list_ptr); - let flags = action_flags::Handle::from_ptr(io_action_flags); + let flags = action_flags::Handle::from_ptr(io_action_flags.as_ptr()); Args { data, - time_stamp: *in_time_stamp, + time_stamp: in_time_stamp.read(), flags, bus_number: in_bus_number as u32, num_frames: in_number_frames as usize, @@ -751,22 +758,20 @@ impl AudioUnit { } /// Callback procedure that will be called each time our audio_unit requests audio. -extern "C" fn input_proc( - in_ref_con: *mut c_void, - io_action_flags: *mut sys::AudioUnitRenderActionFlags, - in_time_stamp: *const sys::AudioTimeStamp, - in_bus_number: sys::UInt32, - in_number_frames: sys::UInt32, +extern "C-unwind" fn input_proc( + in_ref_con: NonNull, + io_action_flags: NonNull, + in_time_stamp: NonNull, + in_bus_number: u32, + in_number_frames: u32, io_data: *mut sys::AudioBufferList, ) -> sys::OSStatus { - let wrapper = in_ref_con as *mut InputProcFnWrapper; - unsafe { - (*(*wrapper).callback)( - io_action_flags, - in_time_stamp, - in_bus_number, - in_number_frames, - io_data, - ) - } + let wrapper = unsafe { in_ref_con.cast::().as_mut() }; + (wrapper.callback)( + io_action_flags, + in_time_stamp, + in_bus_number, + in_number_frames, + io_data, + ) } diff --git a/src/audio_unit/stream_format.rs b/src/audio_unit/stream_format.rs index b982ec7e9..3b78008ce 100644 --- a/src/audio_unit/stream_format.rs +++ b/src/audio_unit/stream_format.rs @@ -6,7 +6,7 @@ use super::audio_format::AudioFormat; use super::audio_format::LinearPcmFlags; use super::SampleFormat; use crate::error::{self, Error}; -use sys; +use crate::sys; /// A representation of the AudioStreamBasicDescription specifically for use with the AudioUnit API. /// diff --git a/src/error.rs b/src/error.rs index c39f80d6f..ff32cbc64 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,10 +4,10 @@ pub use self::audio::Error as AudioError; pub use self::audio_codec::Error as AudioCodecError; pub use self::audio_format::Error as AudioFormatError; pub use self::audio_unit::Error as AudioUnitError; -use sys::OSStatus; +use crate::sys::OSStatus; pub mod audio { - use sys::OSStatus; + use crate::sys::OSStatus; #[derive(Copy, Clone, Debug)] pub enum Error { @@ -61,7 +61,7 @@ pub mod audio { } pub mod audio_codec { - use sys::OSStatus; + use crate::sys::OSStatus; #[derive(Copy, Clone, Debug)] pub enum Error { @@ -115,7 +115,7 @@ pub mod audio_codec { } pub mod audio_format { - use sys::OSStatus; + use crate::sys::OSStatus; // TODO: Finish implementing these values. #[derive(Copy, Clone, Debug)] @@ -162,7 +162,7 @@ pub mod audio_format { } pub mod audio_unit { - use sys::OSStatus; + use crate::sys::OSStatus; #[derive(Copy, Clone, Debug)] pub enum Error { diff --git a/src/lib.rs b/src/lib.rs index 87067b2dc..f02d0c25f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,11 +10,23 @@ #[macro_use] extern crate bitflags; -extern crate core_foundation_sys; -pub extern crate coreaudio_sys as sys; pub use error::Error; -#[cfg(feature = "audio_unit")] +#[cfg(feature = "audio_toolbox")] pub mod audio_unit; pub mod error; + +pub mod sys { + #[cfg(feature = "audio_toolbox")] + pub use objc2_audio_toolbox::*; + #[cfg(feature = "core_audio")] + pub use objc2_core_audio::*; + #[cfg(feature = "core_audio")] + pub use objc2_core_audio_types::*; + #[cfg(feature = "core_midi")] + pub use objc2_core_midi::*; + + // MacTypes.h + pub type OSStatus = i32; +}