From f7cf0c65b8d632b53526aba3e1c6720eae90f692 Mon Sep 17 00:00:00 2001 From: mitchmindtree Date: Mon, 24 Jun 2019 22:44:57 +0200 Subject: [PATCH] Implement `Host` API for coreaudio backend --- src/host/coreaudio/mod.rs | 132 ++++++++++++++++++++++++++++++++++---- 1 file changed, 120 insertions(+), 12 deletions(-) diff --git a/src/host/coreaudio/mod.rs b/src/host/coreaudio/mod.rs index 3cd3613..d37de7b 100644 --- a/src/host/coreaudio/mod.rs +++ b/src/host/coreaudio/mod.rs @@ -5,8 +5,11 @@ use ChannelCount; use BackendSpecificError; use BuildStreamError; use DefaultFormatError; +use Device as DeviceTrait; use DeviceNameError; +use EventLoop as EventLoopTrait; use Format; +use Host as HostTrait; use PauseStreamError; use PlayStreamError; use SupportedFormatsError; @@ -14,6 +17,7 @@ use SampleFormat; use SampleRate; use StreamData; use StreamDataResult; +use StreamId as StreamIdTrait; use SupportedFormat; use UnknownTypeInputBuffer; use UnknownTypeOutputBuffer; @@ -72,13 +76,117 @@ mod enumerate; pub use self::enumerate::{Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device}; +/// Coreaudio host, the default host on macOS and iOS. +#[derive(Debug)] +pub struct Host; + +impl Host { + pub fn new() -> Result { + Ok(Host) + } +} + +impl HostTrait for Host { + type Devices = Devices; + type Device = Device; + type EventLoop = EventLoop; + + fn is_available() -> bool { + // Assume ALSA is always available on linux/freebsd. + true + } + + fn devices(&self) -> Result { + Devices::new() + } + + fn default_input_device(&self) -> Option { + default_input_device() + } + + fn default_output_device(&self) -> Option { + default_output_device() + } + + fn event_loop(&self) -> Self::EventLoop { + EventLoop::new() + } +} + +impl DeviceTrait for Device { + type SupportedInputFormats = SupportedInputFormats; + type SupportedOutputFormats = SupportedOutputFormats; + + fn name(&self) -> Result { + Device::name(self) + } + + fn supported_input_formats(&self) -> Result { + Device::supported_input_formats(self) + } + + fn supported_output_formats(&self) -> Result { + Device::supported_output_formats(self) + } + + fn default_input_format(&self) -> Result { + Device::default_input_format(self) + } + + fn default_output_format(&self) -> Result { + Device::default_output_format(self) + } +} + +impl EventLoopTrait for EventLoop { + type Device = Device; + type StreamId = StreamId; + + fn build_input_stream( + &self, + device: &Self::Device, + format: &Format, + ) -> Result { + EventLoop::build_input_stream(self, device, format) + } + + fn build_output_stream( + &self, + device: &Self::Device, + format: &Format, + ) -> Result { + EventLoop::build_output_stream(self, device, format) + } + + fn play_stream(&self, stream: Self::StreamId) -> Result<(), PlayStreamError> { + EventLoop::play_stream(self, stream) + } + + fn pause_stream(&self, stream: Self::StreamId) -> Result<(), PauseStreamError> { + EventLoop::pause_stream(self, stream) + } + + fn destroy_stream(&self, stream: Self::StreamId) { + EventLoop::destroy_stream(self, stream) + } + + fn run(&self, callback: F) -> ! + where + F: FnMut(Self::StreamId, StreamDataResult) + Send, + { + EventLoop::run(self, callback) + } +} + +impl StreamIdTrait for StreamId {} + #[derive(Clone, PartialEq, Eq)] pub struct Device { audio_device_id: AudioDeviceID, } impl Device { - pub fn name(&self) -> Result { + fn name(&self) -> Result { let property_address = AudioObjectPropertyAddress { mSelector: kAudioDevicePropertyDeviceNameCFString, mScope: kAudioDevicePropertyScopeOutput, @@ -212,11 +320,11 @@ impl Device { } } - pub fn supported_input_formats(&self) -> Result { + fn supported_input_formats(&self) -> Result { self.supported_formats(kAudioObjectPropertyScopeInput) } - pub fn supported_output_formats(&self) -> Result { + fn supported_output_formats(&self) -> Result { self.supported_formats(kAudioObjectPropertyScopeOutput) } @@ -296,11 +404,11 @@ impl Device { } } - pub fn default_input_format(&self) -> Result { + fn default_input_format(&self) -> Result { self.default_format(kAudioObjectPropertyScopeInput) } - pub fn default_output_format(&self) -> Result { + fn default_output_format(&self) -> Result { self.default_format(kAudioObjectPropertyScopeOutput) } } @@ -435,7 +543,7 @@ fn audio_unit_from_device(device: &Device, input: bool) -> Result EventLoop { + fn new() -> EventLoop { EventLoop { user_callback: Arc::new(Mutex::new(UserCallback::Inactive)), streams: Mutex::new(Vec::new()), @@ -443,7 +551,7 @@ impl EventLoop { } #[inline] - pub fn run(&self, mut callback: F) -> ! + fn run(&self, mut callback: F) -> ! where F: FnMut(StreamId, StreamDataResult) + Send { { @@ -490,7 +598,7 @@ impl EventLoop { } #[inline] - pub fn build_input_stream( + fn build_input_stream( &self, device: &Device, format: &Format, @@ -712,7 +820,7 @@ impl EventLoop { } #[inline] - pub fn build_output_stream( + fn build_output_stream( &self, device: &Device, format: &Format, @@ -787,14 +895,14 @@ impl EventLoop { Ok(StreamId(stream_id)) } - pub fn destroy_stream(&self, stream_id: StreamId) { + fn destroy_stream(&self, stream_id: StreamId) { { let mut streams = self.streams.lock().unwrap(); streams[stream_id.0] = None; } } - pub fn play_stream(&self, stream_id: StreamId) -> Result<(), PlayStreamError> { + fn play_stream(&self, stream_id: StreamId) -> Result<(), PlayStreamError> { let mut streams = self.streams.lock().unwrap(); let stream = streams[stream_id.0].as_mut().unwrap(); @@ -809,7 +917,7 @@ impl EventLoop { Ok(()) } - pub fn pause_stream(&self, stream_id: StreamId) -> Result<(), PauseStreamError> { + fn pause_stream(&self, stream_id: StreamId) -> Result<(), PauseStreamError> { let mut streams = self.streams.lock().unwrap(); let stream = streams[stream_id.0].as_mut().unwrap();