1 extern crate coreaudio;
2 extern crate core_foundation_sys;
3
4 use ChannelCount;
5 use CreationError;
6 use DefaultFormatError;
7 use Format;
8 use FormatsEnumerationError;
9 use Sample;
10 use SampleFormat;
11 use SampleRate;
12 use StreamData;
13 use SupportedFormat;
14 use UnknownTypeInputBuffer;
15 use UnknownTypeOutputBuffer;
16
17 use std::ffi::CStr;
18 use std::mem;
19 use std::os::raw::c_char;
20 use std::ptr::null;
21 use std::sync::{Arc, Mutex};
22 use std::thread;
23 use std::time::Duration;
24 use std::slice;
25
26 use self::coreaudio::audio_unit::{AudioUnit, Scope, Element};
27 use self::coreaudio::audio_unit::render_callback::{self, data};
28 use self::coreaudio::sys::{
29 AudioBuffer,
30 AudioBufferList,
31 AudioDeviceID,
32 AudioObjectAddPropertyListener,
33 AudioObjectGetPropertyData,
34 AudioObjectGetPropertyDataSize,
35 AudioObjectID,
36 AudioObjectPropertyAddress,
37 AudioObjectPropertyScope,
38 AudioObjectRemovePropertyListener,
39 AudioObjectSetPropertyData,
40 AudioStreamBasicDescription,
41 AudioValueRange,
42 kAudioDevicePropertyAvailableNominalSampleRates,
43 kAudioDevicePropertyDeviceNameCFString,
44 kAudioDevicePropertyNominalSampleRate,
45 kAudioObjectPropertyScopeInput,
46 kAudioObjectPropertyScopeGlobal,
47 kAudioDevicePropertyScopeOutput,
48 kAudioDevicePropertyStreamConfiguration,
49 kAudioDevicePropertyStreamFormat,
50 kAudioFormatFlagIsFloat,
51 kAudioFormatFlagIsPacked,
52 kAudioFormatLinearPCM,
53 kAudioHardwareNoError,
54 kAudioObjectPropertyElementMaster,
55 kAudioObjectPropertyScopeOutput,
56 kAudioOutputUnitProperty_CurrentDevice,
57 kAudioOutputUnitProperty_EnableIO,
58 kAudioUnitProperty_StreamFormat,
59 kCFStringEncodingUTF8,
60 OSStatus,
61 };
62 use self::core_foundation_sys::string::{
63 CFStringRef,
64 CFStringGetCStringPtr,
65 };
66
67 mod enumerate;
68
69 pub use self::enumerate::{Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device};
70
71 #[derive(Clone, PartialEq, Eq)]
72 pub struct Device {
73 audio_device_id: AudioDeviceID,
74 }
75
76 impl Device {
name(&self) -> String77 pub fn name(&self) -> String {
78 let property_address = AudioObjectPropertyAddress {
79 mSelector: kAudioDevicePropertyDeviceNameCFString,
80 mScope: kAudioDevicePropertyScopeOutput,
81 mElement: kAudioObjectPropertyElementMaster,
82 };
83 let device_name: CFStringRef = null();
84 let data_size = mem::size_of::<CFStringRef>();
85 let c_str = unsafe {
86 let status = AudioObjectGetPropertyData(
87 self.audio_device_id,
88 &property_address as *const _,
89 0,
90 null(),
91 &data_size as *const _ as *mut _,
92 &device_name as *const _ as *mut _,
93 );
94 if status != kAudioHardwareNoError as i32 {
95 return format!("<OSStatus: {:?}>", status);
96 }
97 let c_string: *const c_char = CFStringGetCStringPtr(device_name, kCFStringEncodingUTF8);
98 if c_string == null() {
99 return "<null>".into();
100 }
101 CStr::from_ptr(c_string as *mut _)
102 };
103 c_str.to_string_lossy().into_owned()
104 }
105
106 // Logic re-used between `supported_input_formats` and `supported_output_formats`.
supported_formats( &self, scope: AudioObjectPropertyScope, ) -> Result<SupportedOutputFormats, FormatsEnumerationError>107 fn supported_formats(
108 &self,
109 scope: AudioObjectPropertyScope,
110 ) -> Result<SupportedOutputFormats, FormatsEnumerationError>
111 {
112 let mut property_address = AudioObjectPropertyAddress {
113 mSelector: kAudioDevicePropertyStreamConfiguration,
114 mScope: scope,
115 mElement: kAudioObjectPropertyElementMaster,
116 };
117
118 unsafe {
119 // Retrieve the devices audio buffer list.
120 let data_size = 0u32;
121 let status = AudioObjectGetPropertyDataSize(
122 self.audio_device_id,
123 &property_address as *const _,
124 0,
125 null(),
126 &data_size as *const _ as *mut _,
127 );
128 if status != kAudioHardwareNoError as i32 {
129 unimplemented!();
130 }
131 let mut audio_buffer_list: Vec<u8> = vec![];
132 audio_buffer_list.reserve_exact(data_size as usize);
133 let status = AudioObjectGetPropertyData(
134 self.audio_device_id,
135 &property_address as *const _,
136 0,
137 null(),
138 &data_size as *const _ as *mut _,
139 audio_buffer_list.as_mut_ptr() as *mut _,
140 );
141 if status != kAudioHardwareNoError as i32 {
142 unimplemented!();
143 }
144 let audio_buffer_list = audio_buffer_list.as_mut_ptr() as *mut AudioBufferList;
145
146 // If there's no buffers, skip.
147 if (*audio_buffer_list).mNumberBuffers == 0 {
148 return Ok(vec![].into_iter());
149 }
150
151 // Count the number of channels as the sum of all channels in all output buffers.
152 let n_buffers = (*audio_buffer_list).mNumberBuffers as usize;
153 let first: *const AudioBuffer = (*audio_buffer_list).mBuffers.as_ptr();
154 let buffers: &'static [AudioBuffer] = slice::from_raw_parts(first, n_buffers);
155 let mut n_channels = 0;
156 for buffer in buffers {
157 n_channels += buffer.mNumberChannels as usize;
158 }
159
160 // AFAIK the sample format should always be f32 on macos and i16 on iOS? Feel free to
161 // fix this if more pcm formats are supported.
162 let sample_format = if cfg!(target_os = "ios") {
163 SampleFormat::I16
164 } else {
165 SampleFormat::F32
166 };
167
168 // Get available sample rate ranges.
169 property_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
170 let data_size = 0u32;
171 let status = AudioObjectGetPropertyDataSize(
172 self.audio_device_id,
173 &property_address as *const _,
174 0,
175 null(),
176 &data_size as *const _ as *mut _,
177 );
178 if status != kAudioHardwareNoError as i32 {
179 unimplemented!();
180 }
181 let n_ranges = data_size as usize / mem::size_of::<AudioValueRange>();
182 let mut ranges: Vec<u8> = vec![];
183 ranges.reserve_exact(data_size as usize);
184 let status = AudioObjectGetPropertyData(
185 self.audio_device_id,
186 &property_address as *const _,
187 0,
188 null(),
189 &data_size as *const _ as *mut _,
190 ranges.as_mut_ptr() as *mut _,
191 );
192 if status != kAudioHardwareNoError as i32 {
193 unimplemented!();
194 }
195 let ranges: *mut AudioValueRange = ranges.as_mut_ptr() as *mut _;
196 let ranges: &'static [AudioValueRange] = slice::from_raw_parts(ranges, n_ranges);
197
198 // Collect the supported formats for the device.
199 let mut fmts = vec![];
200 for range in ranges {
201 let fmt = SupportedFormat {
202 channels: n_channels as ChannelCount,
203 min_sample_rate: SampleRate(range.mMinimum as _),
204 max_sample_rate: SampleRate(range.mMaximum as _),
205 data_type: sample_format,
206 };
207 fmts.push(fmt);
208 }
209
210 Ok(fmts.into_iter())
211 }
212 }
213
supported_input_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError>214 pub fn supported_input_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError> {
215 self.supported_formats(kAudioObjectPropertyScopeInput)
216 }
217
supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError>218 pub fn supported_output_formats(&self) -> Result<SupportedOutputFormats, FormatsEnumerationError> {
219 self.supported_formats(kAudioObjectPropertyScopeOutput)
220 }
221
default_format( &self, scope: AudioObjectPropertyScope, ) -> Result<Format, DefaultFormatError>222 fn default_format(
223 &self,
224 scope: AudioObjectPropertyScope,
225 ) -> Result<Format, DefaultFormatError>
226 {
227 fn default_format_error_from_os_status(status: OSStatus) -> Option<DefaultFormatError> {
228 let err = match coreaudio::Error::from_os_status(status) {
229 Err(err) => err,
230 Ok(_) => return None,
231 };
232 match err {
233 coreaudio::Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat |
234 coreaudio::Error::NoKnownSubtype |
235 coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::FormatNotSupported) |
236 coreaudio::Error::AudioCodec(_) |
237 coreaudio::Error::AudioFormat(_) => Some(DefaultFormatError::StreamTypeNotSupported),
238 _ => Some(DefaultFormatError::DeviceNotAvailable),
239 }
240 }
241
242 let property_address = AudioObjectPropertyAddress {
243 mSelector: kAudioDevicePropertyStreamFormat,
244 mScope: scope,
245 mElement: kAudioObjectPropertyElementMaster,
246 };
247
248 unsafe {
249 let asbd: AudioStreamBasicDescription = mem::uninitialized();
250 let data_size = mem::size_of::<AudioStreamBasicDescription>() as u32;
251 let status = AudioObjectGetPropertyData(
252 self.audio_device_id,
253 &property_address as *const _,
254 0,
255 null(),
256 &data_size as *const _ as *mut _,
257 &asbd as *const _ as *mut _,
258 );
259
260 if status != kAudioHardwareNoError as i32 {
261 let err = default_format_error_from_os_status(status)
262 .expect("no known error for OSStatus");
263 return Err(err);
264 }
265
266 let sample_format = {
267 let audio_format = coreaudio::audio_unit::AudioFormat::from_format_and_flag(
268 asbd.mFormatID,
269 Some(asbd.mFormatFlags),
270 );
271 let flags = match audio_format {
272 Some(coreaudio::audio_unit::AudioFormat::LinearPCM(flags)) => flags,
273 _ => return Err(DefaultFormatError::StreamTypeNotSupported),
274 };
275 let maybe_sample_format =
276 coreaudio::audio_unit::SampleFormat::from_flags_and_bytes_per_frame(
277 flags,
278 asbd.mBytesPerFrame,
279 );
280 match maybe_sample_format {
281 Some(coreaudio::audio_unit::SampleFormat::F32) => SampleFormat::F32,
282 Some(coreaudio::audio_unit::SampleFormat::I16) => SampleFormat::I16,
283 _ => return Err(DefaultFormatError::StreamTypeNotSupported),
284 }
285 };
286
287 let format = Format {
288 sample_rate: SampleRate(asbd.mSampleRate as _),
289 channels: asbd.mChannelsPerFrame as _,
290 data_type: sample_format,
291 };
292 Ok(format)
293 }
294 }
295
default_input_format(&self) -> Result<Format, DefaultFormatError>296 pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
297 self.default_format(kAudioObjectPropertyScopeInput)
298 }
299
default_output_format(&self) -> Result<Format, DefaultFormatError>300 pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
301 self.default_format(kAudioObjectPropertyScopeOutput)
302 }
303 }
304
305 // The ID of a stream is its index within the `streams` array of the events loop.
306 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
307 pub struct StreamId(usize);
308
309 pub struct EventLoop {
310 // This `Arc` is shared with all the callbacks of coreaudio.
311 active_callbacks: Arc<ActiveCallbacks>,
312 streams: Mutex<Vec<Option<StreamInner>>>,
313 }
314
315 struct ActiveCallbacks {
316 // Whenever the `run()` method is called with a callback, this callback is put in this list.
317 callbacks: Mutex<Vec<&'static mut (FnMut(StreamId, StreamData) + Send)>>,
318 }
319
320 struct StreamInner {
321 playing: bool,
322 audio_unit: AudioUnit,
323 // Track the device with which the audio unit was spawned.
324 //
325 // We must do this so that we can avoid changing the device sample rate if there is already
326 // a stream associated with the device.
327 device_id: AudioDeviceID,
328 }
329
330 // TODO need stronger error identification
331 impl From<coreaudio::Error> for CreationError {
from(err: coreaudio::Error) -> CreationError332 fn from(err: coreaudio::Error) -> CreationError {
333 match err {
334 coreaudio::Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat |
335 coreaudio::Error::NoKnownSubtype |
336 coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::FormatNotSupported) |
337 coreaudio::Error::AudioCodec(_) |
338 coreaudio::Error::AudioFormat(_) => CreationError::FormatNotSupported,
339 _ => CreationError::DeviceNotAvailable,
340 }
341 }
342 }
343
344 // Create a coreaudio AudioStreamBasicDescription from a CPAL Format.
asbd_from_format(format: &Format) -> AudioStreamBasicDescription345 fn asbd_from_format(format: &Format) -> AudioStreamBasicDescription {
346 let n_channels = format.channels as usize;
347 let sample_rate = format.sample_rate.0;
348 let bytes_per_channel = format.data_type.sample_size();
349 let bits_per_channel = bytes_per_channel * 8;
350 let bytes_per_frame = n_channels * bytes_per_channel;
351 let frames_per_packet = 1;
352 let bytes_per_packet = frames_per_packet * bytes_per_frame;
353 let sample_format = format.data_type;
354 let format_flags = match sample_format {
355 SampleFormat::F32 => (kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked) as u32,
356 _ => kAudioFormatFlagIsPacked as u32,
357 };
358 let asbd = AudioStreamBasicDescription {
359 mBitsPerChannel: bits_per_channel as _,
360 mBytesPerFrame: bytes_per_frame as _,
361 mChannelsPerFrame: n_channels as _,
362 mBytesPerPacket: bytes_per_packet as _,
363 mFramesPerPacket: frames_per_packet as _,
364 mFormatFlags: format_flags,
365 mFormatID: kAudioFormatLinearPCM,
366 mSampleRate: sample_rate as _,
367 ..Default::default()
368 };
369 asbd
370 }
371
audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, coreaudio::Error>372 fn audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, coreaudio::Error> {
373 let mut audio_unit = {
374 let au_type = if cfg!(target_os = "ios") {
375 // The HalOutput unit isn't available in iOS unfortunately.
376 // RemoteIO is a sensible replacement.
377 // See https://goo.gl/CWwRTx
378 coreaudio::audio_unit::IOType::RemoteIO
379 } else {
380 coreaudio::audio_unit::IOType::HalOutput
381 };
382 AudioUnit::new(au_type)?
383 };
384
385 if input {
386 // Enable input processing.
387 let enable_input = 1u32;
388 audio_unit.set_property(
389 kAudioOutputUnitProperty_EnableIO,
390 Scope::Input,
391 Element::Input,
392 Some(&enable_input),
393 )?;
394
395 // Disable output processing.
396 let disable_output = 0u32;
397 audio_unit.set_property(
398 kAudioOutputUnitProperty_EnableIO,
399 Scope::Output,
400 Element::Output,
401 Some(&disable_output),
402 )?;
403 }
404
405 audio_unit.set_property(
406 kAudioOutputUnitProperty_CurrentDevice,
407 Scope::Global,
408 Element::Output,
409 Some(&device.audio_device_id),
410 )?;
411
412 Ok(audio_unit)
413 }
414
415 impl EventLoop {
416 #[inline]
new() -> EventLoop417 pub fn new() -> EventLoop {
418 EventLoop {
419 active_callbacks: Arc::new(ActiveCallbacks { callbacks: Mutex::new(Vec::new()) }),
420 streams: Mutex::new(Vec::new()),
421 }
422 }
423
424 #[inline]
run<F>(&self, mut callback: F) -> ! where F: FnMut(StreamId, StreamData) + Send425 pub fn run<F>(&self, mut callback: F) -> !
426 where F: FnMut(StreamId, StreamData) + Send
427 {
428 {
429 let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback;
430 self.active_callbacks
431 .callbacks
432 .lock()
433 .unwrap()
434 .push(unsafe { mem::transmute(callback) });
435 }
436
437 loop {
438 // So the loop does not get optimised out in --release
439 thread::sleep(Duration::new(1u64, 0u32));
440 }
441
442 // Note: if we ever change this API so that `run` can return, then it is critical that
443 // we remove the callback from `active_callbacks`.
444 }
445
next_stream_id(&self) -> usize446 fn next_stream_id(&self) -> usize {
447 let streams_lock = self.streams.lock().unwrap();
448 let stream_id = streams_lock
449 .iter()
450 .position(|n| n.is_none())
451 .unwrap_or(streams_lock.len());
452 stream_id
453 }
454
455 // Add the stream to the list of streams within `self`.
add_stream(&self, stream_id: usize, au: AudioUnit, device_id: AudioDeviceID)456 fn add_stream(&self, stream_id: usize, au: AudioUnit, device_id: AudioDeviceID) {
457 let inner = StreamInner {
458 playing: true,
459 audio_unit: au,
460 device_id: device_id,
461 };
462
463 let mut streams_lock = self.streams.lock().unwrap();
464 if stream_id == streams_lock.len() {
465 streams_lock.push(Some(inner));
466 } else {
467 streams_lock[stream_id] = Some(inner);
468 }
469 }
470
471 #[inline]
build_input_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>472 pub fn build_input_stream(
473 &self,
474 device: &Device,
475 format: &Format,
476 ) -> Result<StreamId, CreationError>
477 {
478 // The scope and element for working with a device's input stream.
479 let scope = Scope::Output;
480 let element = Element::Input;
481
482 // Check whether or not we need to change the device sample rate to suit the one specified for the stream.
483 unsafe {
484 // Get the current sample rate.
485 let mut property_address = AudioObjectPropertyAddress {
486 mSelector: kAudioDevicePropertyNominalSampleRate,
487 mScope: kAudioObjectPropertyScopeGlobal,
488 mElement: kAudioObjectPropertyElementMaster,
489 };
490 let sample_rate: f64 = 0.0;
491 let data_size = mem::size_of::<f64>() as u32;
492 let status = AudioObjectGetPropertyData(
493 device.audio_device_id,
494 &property_address as *const _,
495 0,
496 null(),
497 &data_size as *const _ as *mut _,
498 &sample_rate as *const _ as *mut _,
499 );
500 coreaudio::Error::from_os_status(status)?;
501
502 // If the requested sample rate is different to the device sample rate, update the device.
503 if sample_rate as u32 != format.sample_rate.0 {
504
505 // In order to avoid breaking existing input streams we `panic!` if there is already an
506 // active input stream for this device with the actual sample rate.
507 for stream in &*self.streams.lock().unwrap() {
508 if let Some(stream) = stream.as_ref() {
509 if stream.device_id == device.audio_device_id {
510 panic!("cannot change device sample rate for stream as an existing stream \
511 is already running at the current sample rate.");
512 }
513 }
514 }
515
516 // Get available sample rate ranges.
517 property_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
518 let data_size = 0u32;
519 let status = AudioObjectGetPropertyDataSize(
520 device.audio_device_id,
521 &property_address as *const _,
522 0,
523 null(),
524 &data_size as *const _ as *mut _,
525 );
526 coreaudio::Error::from_os_status(status)?;
527 let n_ranges = data_size as usize / mem::size_of::<AudioValueRange>();
528 let mut ranges: Vec<u8> = vec![];
529 ranges.reserve_exact(data_size as usize);
530 let status = AudioObjectGetPropertyData(
531 device.audio_device_id,
532 &property_address as *const _,
533 0,
534 null(),
535 &data_size as *const _ as *mut _,
536 ranges.as_mut_ptr() as *mut _,
537 );
538 coreaudio::Error::from_os_status(status)?;
539 let ranges: *mut AudioValueRange = ranges.as_mut_ptr() as *mut _;
540 let ranges: &'static [AudioValueRange] = slice::from_raw_parts(ranges, n_ranges);
541
542 // Now that we have the available ranges, pick the one matching the desired rate.
543 let sample_rate = format.sample_rate.0;
544 let maybe_index = ranges
545 .iter()
546 .position(|r| r.mMinimum as u32 == sample_rate && r.mMaximum as u32 == sample_rate);
547 let range_index = match maybe_index {
548 None => return Err(CreationError::FormatNotSupported),
549 Some(i) => i,
550 };
551
552 // Update the property selector to specify the nominal sample rate.
553 property_address.mSelector = kAudioDevicePropertyNominalSampleRate;
554
555 // Setting the sample rate of a device is an asynchronous process in coreaudio.
556 //
557 // Thus we are required to set a `listener` so that we may be notified when the
558 // change occurs.
559 unsafe extern "C" fn rate_listener(
560 device_id: AudioObjectID,
561 _n_addresses: u32,
562 _properties: *const AudioObjectPropertyAddress,
563 rate_ptr: *mut ::std::os::raw::c_void,
564 ) -> OSStatus {
565 let rate_ptr: *const f64 = rate_ptr as *const _;
566 let data_size = mem::size_of::<f64>();
567 let property_address = AudioObjectPropertyAddress {
568 mSelector: kAudioDevicePropertyNominalSampleRate,
569 mScope: kAudioObjectPropertyScopeGlobal,
570 mElement: kAudioObjectPropertyElementMaster,
571 };
572 AudioObjectGetPropertyData(
573 device_id,
574 &property_address as *const _,
575 0,
576 null(),
577 &data_size as *const _ as *mut _,
578 rate_ptr as *const _ as *mut _,
579 )
580 }
581
582 // Add our sample rate change listener callback.
583 let reported_rate: f64 = 0.0;
584 let status = AudioObjectAddPropertyListener(
585 device.audio_device_id,
586 &property_address as *const _,
587 Some(rate_listener),
588 &reported_rate as *const _ as *mut _,
589 );
590 coreaudio::Error::from_os_status(status)?;
591
592 // Finally, set the sample rate.
593 let sample_rate = sample_rate as f64;
594 let status = AudioObjectSetPropertyData(
595 device.audio_device_id,
596 &property_address as *const _,
597 0,
598 null(),
599 data_size,
600 &ranges[range_index] as *const _ as *const _,
601 );
602 coreaudio::Error::from_os_status(status)?;
603
604 // Wait for the reported_rate to change.
605 //
606 // This should not take longer than a few ms, but we timeout after 1 sec just in case.
607 let timer = ::std::time::Instant::now();
608 while sample_rate != reported_rate {
609 if timer.elapsed() > ::std::time::Duration::from_secs(1) {
610 panic!("timeout waiting for sample rate update for device");
611 }
612 ::std::thread::sleep(::std::time::Duration::from_millis(5));
613 }
614
615 // Remove the `rate_listener` callback.
616 let status = AudioObjectRemovePropertyListener(
617 device.audio_device_id,
618 &property_address as *const _,
619 Some(rate_listener),
620 &reported_rate as *const _ as *mut _,
621 );
622 coreaudio::Error::from_os_status(status)?;
623 }
624 }
625
626 let mut audio_unit = audio_unit_from_device(device, true)?;
627
628 // Set the stream in interleaved mode.
629 let asbd = asbd_from_format(format);
630 audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
631
632 // Determine the future ID of the stream.
633 let stream_id = self.next_stream_id();
634
635 // Register the callback that is being called by coreaudio whenever it needs data to be
636 // fed to the audio buffer.
637 let active_callbacks = self.active_callbacks.clone();
638 let sample_format = format.data_type;
639 let bytes_per_channel = format.data_type.sample_size();
640 type Args = render_callback::Args<data::Raw>;
641 audio_unit.set_input_callback(move |args: Args| unsafe {
642 let ptr = (*args.data.data).mBuffers.as_ptr() as *const AudioBuffer;
643 let len = (*args.data.data).mNumberBuffers as usize;
644 let buffers: &[AudioBuffer] = slice::from_raw_parts(ptr, len);
645
646 // TODO: Perhaps loop over all buffers instead?
647 let AudioBuffer {
648 mNumberChannels: _num_channels,
649 mDataByteSize: data_byte_size,
650 mData: data
651 } = buffers[0];
652
653 let mut callbacks = active_callbacks.callbacks.lock().unwrap();
654
655 // A small macro to simplify handling the callback for different sample types.
656 macro_rules! try_callback {
657 ($SampleFormat:ident, $SampleType:ty) => {{
658 let data_len = (data_byte_size as usize / bytes_per_channel) as usize;
659 let data_slice = slice::from_raw_parts(data as *const $SampleType, data_len);
660 let callback = match callbacks.get_mut(0) {
661 Some(cb) => cb,
662 None => return Ok(()),
663 };
664 let buffer = InputBuffer { buffer: data_slice };
665 let unknown_type_buffer = UnknownTypeInputBuffer::$SampleFormat(::InputBuffer { buffer: Some(buffer) });
666 let stream_data = StreamData::Input { buffer: unknown_type_buffer };
667 callback(StreamId(stream_id), stream_data);
668 }};
669 }
670
671 match sample_format {
672 SampleFormat::F32 => try_callback!(F32, f32),
673 SampleFormat::I16 => try_callback!(I16, i16),
674 SampleFormat::U16 => try_callback!(U16, u16),
675 }
676
677 Ok(())
678 })?;
679
680 // TODO: start playing now? is that consistent with the other backends?
681 audio_unit.start()?;
682
683 // Add the stream to the list of streams within `self`.
684 self.add_stream(stream_id, audio_unit, device.audio_device_id);
685
686 Ok(StreamId(stream_id))
687 }
688
689 #[inline]
build_output_stream( &self, device: &Device, format: &Format, ) -> Result<StreamId, CreationError>690 pub fn build_output_stream(
691 &self,
692 device: &Device,
693 format: &Format,
694 ) -> Result<StreamId, CreationError>
695 {
696 let mut audio_unit = audio_unit_from_device(device, false)?;
697
698 // The scope and element for working with a device's output stream.
699 let scope = Scope::Input;
700 let element = Element::Output;
701
702 // Set the stream in interleaved mode.
703 let asbd = asbd_from_format(format);
704 audio_unit.set_property(kAudioUnitProperty_StreamFormat, scope, element, Some(&asbd))?;
705
706 // Determine the future ID of the stream.
707 let stream_id = self.next_stream_id();
708
709 // Register the callback that is being called by coreaudio whenever it needs data to be
710 // fed to the audio buffer.
711 let active_callbacks = self.active_callbacks.clone();
712 let sample_format = format.data_type;
713 let bytes_per_channel = format.data_type.sample_size();
714 type Args = render_callback::Args<data::Raw>;
715 audio_unit.set_render_callback(move |args: Args| unsafe {
716 // If `run()` is currently running, then a callback will be available from this list.
717 // Otherwise, we just fill the buffer with zeroes and return.
718
719 let AudioBuffer {
720 mNumberChannels: _num_channels,
721 mDataByteSize: data_byte_size,
722 mData: data
723 } = (*args.data.data).mBuffers[0];
724
725 let mut callbacks = active_callbacks.callbacks.lock().unwrap();
726
727 // A small macro to simplify handling the callback for different sample types.
728 macro_rules! try_callback {
729 ($SampleFormat:ident, $SampleType:ty, $equilibrium:expr) => {{
730 let data_len = (data_byte_size as usize / bytes_per_channel) as usize;
731 let data_slice = slice::from_raw_parts_mut(data as *mut $SampleType, data_len);
732 let callback = match callbacks.get_mut(0) {
733 Some(cb) => cb,
734 None => {
735 for sample in data_slice.iter_mut() {
736 *sample = $equilibrium;
737 }
738 return Ok(());
739 }
740 };
741 let buffer = OutputBuffer { buffer: data_slice };
742 let unknown_type_buffer = UnknownTypeOutputBuffer::$SampleFormat(::OutputBuffer { target: Some(buffer) });
743 let stream_data = StreamData::Output { buffer: unknown_type_buffer };
744 callback(StreamId(stream_id), stream_data);
745 }};
746 }
747
748 match sample_format {
749 SampleFormat::F32 => try_callback!(F32, f32, 0.0),
750 SampleFormat::I16 => try_callback!(I16, i16, 0),
751 SampleFormat::U16 => try_callback!(U16, u16, ::std::u16::MAX / 2),
752 }
753
754 Ok(())
755 })?;
756
757 // TODO: start playing now? is that consistent with the other backends?
758 audio_unit.start()?;
759
760 // Add the stream to the list of streams within `self`.
761 self.add_stream(stream_id, audio_unit, device.audio_device_id);
762
763 Ok(StreamId(stream_id))
764 }
765
destroy_stream(&self, stream_id: StreamId)766 pub fn destroy_stream(&self, stream_id: StreamId) {
767 let mut streams = self.streams.lock().unwrap();
768 streams[stream_id.0] = None;
769 }
770
play_stream(&self, stream: StreamId)771 pub fn play_stream(&self, stream: StreamId) {
772 let mut streams = self.streams.lock().unwrap();
773 let stream = streams[stream.0].as_mut().unwrap();
774
775 if !stream.playing {
776 stream.audio_unit.start().unwrap();
777 stream.playing = true;
778 }
779 }
780
pause_stream(&self, stream: StreamId)781 pub fn pause_stream(&self, stream: StreamId) {
782 let mut streams = self.streams.lock().unwrap();
783 let stream = streams[stream.0].as_mut().unwrap();
784
785 if stream.playing {
786 stream.audio_unit.stop().unwrap();
787 stream.playing = false;
788 }
789 }
790 }
791
792 pub struct InputBuffer<'a, T: 'a> {
793 buffer: &'a [T],
794 }
795
796 pub struct OutputBuffer<'a, T: 'a> {
797 buffer: &'a mut [T],
798 }
799
800 impl<'a, T> InputBuffer<'a, T> {
801 #[inline]
buffer(&self) -> &[T]802 pub fn buffer(&self) -> &[T] {
803 &self.buffer
804 }
805
806 #[inline]
finish(self)807 pub fn finish(self) {
808 // Nothing to be done.
809 }
810 }
811
812 impl<'a, T> OutputBuffer<'a, T>
813 where T: Sample
814 {
815 #[inline]
buffer(&mut self) -> &mut [T]816 pub fn buffer(&mut self) -> &mut [T] {
817 &mut self.buffer
818 }
819
820 #[inline]
len(&self) -> usize821 pub fn len(&self) -> usize {
822 self.buffer.len()
823 }
824
825 #[inline]
finish(self)826 pub fn finish(self) {
827 // Do nothing. We wrote directly to the buffer.
828 }
829 }
830