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