Skip to content

Commit 9b2b23b

Browse files
Make uninitialized audio units available (#152)
* constructor for audio unit without initialization * initialize in helper only after settings, add new helper * restore default device functionality for audio unit
1 parent e7483c3 commit 9b2b23b

2 files changed

Lines changed: 57 additions & 5 deletions

File tree

src/audio_unit/macos_helpers.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,28 @@ pub fn get_device_id_from_name(name: &str, input: bool) -> Option<AudioDeviceID>
9191
}
9292

9393
/// Create an AudioUnit instance from a device id.
94-
/// Set `input` to `true` to create a playback device, or `false` for a capture device.
94+
/// Set `input` to `true` to create a capture device, or `false` for a playback device.
9595
pub fn audio_unit_from_device_id(
9696
device_id: AudioDeviceID,
9797
input: bool,
9898
) -> Result<AudioUnit, Error> {
99-
let mut audio_unit = AudioUnit::new(IOType::HalOutput)?;
99+
let mut audio_unit = audio_unit_from_device_id_uninitialized(device_id, input)?;
100+
audio_unit.initialize()?;
101+
Ok(audio_unit)
102+
}
103+
104+
/// Create an AudioUnit instance from a device id without initializing it.
105+
/// Set `input` to `true` to create a capture device, or `false` for a playback device.
106+
pub fn audio_unit_from_device_id_uninitialized(
107+
device_id: AudioDeviceID,
108+
input: bool,
109+
) -> Result<AudioUnit, Error> {
110+
let output_type = if !input && get_default_device_id(false).is_some_and(|d| d == device_id) {
111+
IOType::DefaultOutput
112+
} else {
113+
IOType::HalOutput
114+
};
115+
let mut audio_unit = AudioUnit::new_uninitialized(output_type)?;
100116

101117
if input {
102118
// Enable input processing.

src/audio_unit/mod.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,36 @@ impl AudioUnit {
124124
AudioUnit::new_with_flags(ty, 0, 0)
125125
}
126126

127+
/// Construct a new AudioUnit with any type that may be automatically converted into
128+
/// [**Type**](./enum.Type). This constructor leaves the audio unit uninitialized
129+
/// for the caller to decide when to do it manually!
130+
///
131+
/// Here is a list of compatible types:
132+
///
133+
/// - [**Type**](./types/enum.Type)
134+
/// - [**IOType**](./types/enum.IOType)
135+
/// - [**MusicDeviceType**](./types/enum.MusicDeviceType)
136+
/// - [**GeneratorType**](./types/enum.GeneratorType)
137+
/// - [**FormatConverterType**](./types/enum.FormatConverterType)
138+
/// - [**EffectType**](./types/enum.EffectType)
139+
/// - [**MixerType**](./types/enum.MixerType)
140+
///
141+
/// To construct the **AudioUnit** with some component flags, see
142+
/// [**AudioUnit::new_with_flags**](./struct.AudioUnit#method.new_with_flags).
143+
///
144+
/// Note: the `AudioUnit` is constructed with the `kAudioUnitManufacturer_Apple` Manufacturer
145+
/// Identifier, as this is the only Audio Unit Manufacturer Identifier documented by Apple in
146+
/// the AudioUnit reference (see [here](https://developer.apple.com/library/prerelease/mac/documentation/AudioUnit/Reference/AUComponentServicesReference/index.html#//apple_ref/doc/constant_group/Audio_Unit_Manufacturer_Identifier)).
147+
pub fn new_uninitialized<T>(ty: T) -> Result<AudioUnit, Error>
148+
where
149+
T: Into<Type>,
150+
{
151+
AudioUnit::new_with_flags_uninitialized(ty, 0, 0)
152+
}
153+
127154
/// The same as [**AudioUnit::new**](./struct.AudioUnit#method.new) but with the given
128155
/// component flags and mask.
129-
pub fn new_with_flags<T>(ty: T, flags: u32, mask: u32) -> Result<AudioUnit, Error>
156+
pub fn new_with_flags_uninitialized<T>(ty: T, flags: u32, mask: u32) -> Result<AudioUnit, Error>
130157
where
131158
T: Into<Type>,
132159
{
@@ -168,8 +195,6 @@ impl AudioUnit {
168195
));
169196
let instance: InnerAudioUnit = instance_uninit.assume_init();
170197

171-
// Initialise the audio unit!
172-
try_os_status!(AudioUnitInitialize(instance));
173198
Ok(AudioUnit {
174199
instance,
175200
maybe_render_callback: None,
@@ -178,6 +203,17 @@ impl AudioUnit {
178203
}
179204
}
180205

206+
/// The same as [**AudioUnit::new**](./struct.AudioUnit#method.new) but with the given
207+
/// component flags and mask.
208+
pub fn new_with_flags<T>(ty: T, flags: u32, mask: u32) -> Result<AudioUnit, Error>
209+
where
210+
T: Into<Type>,
211+
{
212+
let mut audio_unit = AudioUnit::new_with_flags_uninitialized(ty, flags, mask)?;
213+
audio_unit.initialize()?;
214+
Ok(audio_unit)
215+
}
216+
181217
/// On successful initialization, the audio formats for input and output are valid
182218
/// and the audio unit is ready to render. During initialization, an audio unit
183219
/// allocates memory according to the maximum number of audio frames it can produce

0 commit comments

Comments
 (0)