From d984013e4529d6cb8c91fb25de16f2624b97b3ac Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 26 Jan 2025 22:00:50 +0100 Subject: [PATCH] Update coreaudio-rs --- Cargo.toml | 25 ++- src/host/coreaudio/ios/mod.rs | 13 +- src/host/coreaudio/macos/enumerate.rs | 52 +++--- src/host/coreaudio/macos/mod.rs | 157 +++++++----------- src/host/coreaudio/macos/property_listener.rs | 15 +- src/host/coreaudio/mod.rs | 10 +- 6 files changed, 119 insertions(+), 153 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0951baa01..745d7734a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,14 +46,27 @@ audio_thread_priority = { version = "0.33.0", optional = true } jack = { version = "0.13.0", optional = true } [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -core-foundation-sys = "0.8.2" # For linking to CoreFoundation.framework and handling device name `CFString`s. mach2 = "0.4" # For access to mach_timebase type. -[target.'cfg(target_os = "macos")'.dependencies] -coreaudio-rs = { version = "0.11", default-features = false, features = ["audio_unit", "core_audio"] } - -[target.'cfg(target_os = "ios")'.dependencies] -coreaudio-rs = { version = "0.11", default-features = false, features = ["audio_unit", "core_audio", "audio_toolbox"] } +[target.'cfg(target_vendor = "apple")'.dependencies] +coreaudio-rs = { version = "0.13.0", default-features = false, features = [ + "core_audio", + "audio_toolbox", +] } +objc2-core-audio = { version = "0.3.1", default-features = false, features = [ + "std", + "AudioHardware", + "AudioHardwareDeprecated", +] } +objc2-audio-toolbox = { version = "0.3.1", default-features = false, features = [ + "std", + "AUComponent", + "AudioUnitProperties", +] } +objc2-core-audio-types = { version = "0.3.1", default-features = false, features = [ + "std", + "CoreAudioBaseTypes", +] } [target.'cfg(target_os = "emscripten")'.dependencies] wasm-bindgen = { version = "0.2.89" } diff --git a/src/host/coreaudio/ios/mod.rs b/src/host/coreaudio/ios/mod.rs index 8d7176c61..753bbd099 100644 --- a/src/host/coreaudio/ios/mod.rs +++ b/src/host/coreaudio/ios/mod.rs @@ -7,17 +7,12 @@ //! buffer size. //! -extern crate core_foundation_sys; -extern crate coreaudio; - use std::cell::RefCell; -use self::coreaudio::audio_unit::render_callback::data; -use self::coreaudio::audio_unit::{render_callback, AudioUnit, Element, Scope}; -use self::coreaudio::sys::{ - kAudioOutputUnitProperty_EnableIO, kAudioUnitProperty_StreamFormat, AudioBuffer, - AudioStreamBasicDescription, -}; +use coreaudio::audio_unit::render_callback::data; +use coreaudio::audio_unit::{render_callback, AudioUnit, Element, Scope}; +use objc2_audio_toolbox::{kAudioOutputUnitProperty_EnableIO, kAudioUnitProperty_StreamFormat}; +use objc2_core_audio_types::{AudioBuffer, AudioStreamBasicDescription}; use super::{asbd_from_config, frames_to_duration, host_time_to_stream_instant}; use crate::traits::{DeviceTrait, HostTrait, StreamTrait}; diff --git a/src/host/coreaudio/macos/enumerate.rs b/src/host/coreaudio/macos/enumerate.rs index 8d15f18e1..e81a85523 100644 --- a/src/host/coreaudio/macos/enumerate.rs +++ b/src/host/coreaudio/macos/enumerate.rs @@ -1,16 +1,14 @@ -extern crate coreaudio; - -use self::coreaudio::sys::{ +use super::{Device, OSStatus}; +use crate::{BackendSpecificError, DevicesError, SupportedStreamConfigRange}; +use objc2_core_audio::{ kAudioHardwareNoError, kAudioHardwarePropertyDefaultInputDevice, kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDevices, kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject, - AudioDeviceID, AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize, - AudioObjectPropertyAddress, OSStatus, + AudioDeviceID, AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize, AudioObjectID, + AudioObjectPropertyAddress, }; -use super::Device; -use crate::{BackendSpecificError, DevicesError, SupportedStreamConfigRange}; use std::mem; -use std::ptr::null; +use std::ptr::{null, NonNull}; use std::vec::IntoIter as VecIntoIter; unsafe fn audio_devices() -> Result, OSStatus> { @@ -30,11 +28,11 @@ unsafe fn audio_devices() -> Result, OSStatus> { let data_size = 0u32; let status = AudioObjectGetPropertyDataSize( - kAudioObjectSystemObject, - &property_address as *const _, + kAudioObjectSystemObject as AudioObjectID, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&data_size), ); try_status_or_return!(status); @@ -43,12 +41,12 @@ unsafe fn audio_devices() -> Result, OSStatus> { audio_devices.reserve_exact(device_count as usize); let status = 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); @@ -95,16 +93,16 @@ pub fn default_input_device() -> 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 { @@ -125,16 +123,16 @@ pub fn default_output_device() -> 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 { diff --git a/src/host/coreaudio/macos/mod.rs b/src/host/coreaudio/macos/mod.rs index 49ad5d144..9de51f6de 100644 --- a/src/host/coreaudio/macos/mod.rs +++ b/src/host/coreaudio/macos/mod.rs @@ -1,25 +1,7 @@ -extern crate core_foundation_sys; -extern crate coreaudio; - +#![allow(deprecated)] use super::{asbd_from_config, check_os_status, frames_to_duration, host_time_to_stream_instant}; -use self::core_foundation_sys::string::{CFStringGetCString, CFStringGetCStringPtr, CFStringRef}; -use self::coreaudio::audio_unit::render_callback::{self, data}; -use self::coreaudio::audio_unit::{AudioUnit, Element, Scope}; -use self::coreaudio::sys::{ - kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyBufferFrameSize, - kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyDeviceIsAlive, - kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyNominalSampleRate, - kAudioDevicePropertyScopeOutput, kAudioDevicePropertyStreamConfiguration, - kAudioDevicePropertyStreamFormat, kAudioObjectPropertyElementMaster, - kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeInput, - kAudioObjectPropertyScopeOutput, kAudioOutputUnitProperty_CurrentDevice, - kAudioOutputUnitProperty_EnableIO, kAudioUnitProperty_StreamFormat, kCFStringEncodingUTF8, - AudioBuffer, AudioBufferList, AudioDeviceID, AudioObjectGetPropertyData, - AudioObjectGetPropertyDataSize, AudioObjectID, AudioObjectPropertyAddress, - AudioObjectPropertyScope, AudioObjectSetPropertyData, AudioStreamBasicDescription, - AudioValueRange, OSStatus, -}; +use super::OSStatus; use crate::traits::{DeviceTrait, HostTrait, StreamTrait}; use crate::{ BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data, @@ -28,11 +10,28 @@ use crate::{ SupportedBufferSize, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError, }; -use std::ffi::CStr; +use coreaudio::audio_unit::render_callback::{self, data}; +use coreaudio::audio_unit::{AudioUnit, Element, Scope}; +use objc2_audio_toolbox::{ + kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO, + kAudioUnitProperty_StreamFormat, +}; +use objc2_core_audio::{ + kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyBufferFrameSize, + kAudioDevicePropertyBufferFrameSizeRange, kAudioDevicePropertyDeviceIsAlive, + kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyStreamConfiguration, + kAudioDevicePropertyStreamFormat, kAudioObjectPropertyElementMaster, + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeInput, + kAudioObjectPropertyScopeOutput, AudioDeviceID, AudioObjectGetPropertyData, + AudioObjectGetPropertyDataSize, AudioObjectID, AudioObjectPropertyAddress, + AudioObjectPropertyScope, AudioObjectSetPropertyData, +}; +use objc2_core_audio_types::{ + AudioBuffer, AudioBufferList, AudioStreamBasicDescription, AudioValueRange, +}; use std::fmt; use std::mem; -use std::os::raw::c_char; -use std::ptr::null; +use std::ptr::{null, NonNull}; use std::slice; use std::sync::mpsc::{channel, RecvTimeoutError}; use std::sync::{Arc, Mutex}; @@ -43,6 +42,7 @@ pub use self::enumerate::{ SupportedOutputConfigs, }; +use coreaudio::audio_unit::macos_helpers::get_device_name; use property_listener::AudioObjectPropertyListener; pub mod enumerate; @@ -162,54 +162,11 @@ pub struct Device { impl Device { fn name(&self) -> Result { - let property_address = AudioObjectPropertyAddress { - mSelector: kAudioDevicePropertyDeviceNameCFString, - mScope: kAudioDevicePropertyScopeOutput, - mElement: kAudioObjectPropertyElementMaster, - }; - let device_name: CFStringRef = null(); - let data_size = mem::size_of::(); - let c_str = unsafe { - let status = AudioObjectGetPropertyData( - self.audio_device_id, - &property_address as *const _, - 0, - null(), - &data_size as *const _ as *mut _, - &device_name as *const _ as *mut _, - ); - check_os_status(status)?; - - let c_string: *const c_char = CFStringGetCStringPtr(device_name, kCFStringEncodingUTF8); - if c_string.is_null() { - let status = AudioObjectGetPropertyData( - self.audio_device_id, - &property_address as *const _, - 0, - null(), - &data_size as *const _ as *mut _, - &device_name as *const _ as *mut _, - ); - check_os_status(status)?; - let mut buf: [i8; 255] = [0; 255]; - let result = CFStringGetCString( - device_name, - buf.as_mut_ptr(), - buf.len() as _, - kCFStringEncodingUTF8, - ); - if result == 0 { - let description = - "core foundation failed to return device name string".to_string(); - let err = BackendSpecificError { description }; - return Err(err.into()); - } - 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()) + get_device_name(self.audio_device_id).map_err(|err| DeviceNameError::BackendSpecific { + err: BackendSpecificError { + description: err.to_string(), + }, + }) } // Logic re-used between `supported_input_configs` and `supported_output_configs`. @@ -229,10 +186,10 @@ impl Device { let data_size = 0u32; let status = AudioObjectGetPropertyDataSize( self.audio_device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&data_size), ); check_os_status(status)?; @@ -240,11 +197,11 @@ impl Device { audio_buffer_list.reserve_exact(data_size as usize); let status = AudioObjectGetPropertyData( self.audio_device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - audio_buffer_list.as_mut_ptr() as *mut _, + NonNull::from(&data_size), + NonNull::new(audio_buffer_list.as_mut_ptr()).unwrap().cast(), ); check_os_status(status)?; @@ -273,10 +230,10 @@ impl Device { let data_size = 0u32; let status = AudioObjectGetPropertyDataSize( self.audio_device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&data_size), ); check_os_status(status)?; @@ -285,11 +242,11 @@ impl Device { ranges.reserve_exact(data_size as usize); let status = AudioObjectGetPropertyData( self.audio_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(), ); check_os_status(status)?; @@ -376,15 +333,15 @@ impl Device { }; unsafe { - let asbd: AudioStreamBasicDescription = mem::zeroed(); + let mut asbd: AudioStreamBasicDescription = mem::zeroed(); let data_size = mem::size_of::() as u32; let status = AudioObjectGetPropertyData( self.audio_device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, - &asbd as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut asbd).cast(), ); default_config_error_from_os_status(status)?; @@ -790,16 +747,16 @@ fn set_sample_rate( 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 = unsafe { AudioObjectGetPropertyData( audio_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(), ) }; coreaudio::Error::from_os_status(status)?; @@ -812,10 +769,10 @@ fn set_sample_rate( let status = unsafe { AudioObjectGetPropertyDataSize( audio_device_id, - &property_address as *const _, + NonNull::from(&property_address), 0, null(), - &data_size as *const _ as *mut _, + NonNull::from(&data_size), ) }; coreaudio::Error::from_os_status(status)?; @@ -825,11 +782,11 @@ fn set_sample_rate( let status = unsafe { AudioObjectGetPropertyData( audio_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(), ) }; coreaudio::Error::from_os_status(status)?; @@ -855,16 +812,16 @@ fn set_sample_rate( // Send sample rate updates back on a channel. let sample_rate_handler = move || { let mut rate: f64 = 0.0; - let data_size = mem::size_of::(); + let data_size = mem::size_of::() as u32; let result = unsafe { AudioObjectGetPropertyData( audio_device_id, - &sample_rate_address as *const _, + NonNull::from(&sample_rate_address), 0, null(), - &data_size as *const _ as *mut _, - &mut rate as *const _ as *mut _, + NonNull::from(&data_size), + NonNull::from(&mut rate).cast(), ) }; send.send(coreaudio::Error::from_os_status(result).map(|_| rate)) @@ -882,11 +839,11 @@ fn set_sample_rate( let status = unsafe { AudioObjectSetPropertyData( audio_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(), ) }; coreaudio::Error::from_os_status(status)?; diff --git a/src/host/coreaudio/macos/property_listener.rs b/src/host/coreaudio/macos/property_listener.rs index cbe8ec2c2..f65f513f1 100644 --- a/src/host/coreaudio/macos/property_listener.rs +++ b/src/host/coreaudio/macos/property_listener.rs @@ -1,9 +1,12 @@ //! Helper code for registering audio object property listeners. -use super::coreaudio::sys::{ +use std::ptr::NonNull; + +use objc2_core_audio::{ AudioObjectAddPropertyListener, AudioObjectID, AudioObjectPropertyAddress, - AudioObjectRemovePropertyListener, OSStatus, + AudioObjectRemovePropertyListener, }; +use super::OSStatus; use crate::BuildStreamError; /// A double-indirection to be able to pass a closure (a fat pointer) @@ -30,7 +33,7 @@ impl AudioObjectPropertyListener { unsafe { coreaudio::Error::from_os_status(AudioObjectAddPropertyListener( audio_object_id, - &property_address as *const _, + NonNull::from(&property_address), Some(property_listener_handler_shim), &*callback as *const _ as *mut _, ))?; @@ -54,7 +57,7 @@ impl AudioObjectPropertyListener { unsafe { coreaudio::Error::from_os_status(AudioObjectRemovePropertyListener( self.audio_object_id, - &self.property_address as *const _, + NonNull::from(&self.property_address), Some(property_listener_handler_shim), &*self.callback as *const _ as *mut _, ))?; @@ -73,10 +76,10 @@ impl Drop for AudioObjectPropertyListener { } /// Callback used to call user-provided closure as a property listener. -unsafe extern "C" fn property_listener_handler_shim( +unsafe extern "C-unwind" fn property_listener_handler_shim( _: AudioObjectID, _: u32, - _: *const AudioObjectPropertyAddress, + _: NonNull, callback: *mut ::std::os::raw::c_void, ) -> OSStatus { let wrapper = callback as *mut PropertyListenerCallbackWrapper; diff --git a/src/host/coreaudio/mod.rs b/src/host/coreaudio/mod.rs index 2e4e6b832..9133d7cec 100644 --- a/src/host/coreaudio/mod.rs +++ b/src/host/coreaudio/mod.rs @@ -1,8 +1,6 @@ -extern crate coreaudio; - -use self::coreaudio::sys::{ +use objc2_core_audio_types::{ kAudioFormatFlagIsFloat, kAudioFormatFlagIsPacked, kAudioFormatFlagIsSignedInteger, - kAudioFormatLinearPCM, AudioStreamBasicDescription, OSStatus, + kAudioFormatLinearPCM, AudioStreamBasicDescription, }; use crate::DefaultStreamConfigError; @@ -67,7 +65,7 @@ fn asbd_from_config( mFormatFlags: format_flags, mFormatID: kAudioFormatLinearPCM, mSampleRate: sample_rate as _, - ..Default::default() + mReserved: 0, } } @@ -122,3 +120,5 @@ impl From for DefaultStreamConfigError { DefaultStreamConfigError::BackendSpecific { err } } } + +pub(crate) type OSStatus = i32;