Implement `Host` API for coreaudio backend

This commit is contained in:
mitchmindtree 2019-06-24 22:44:57 +02:00
parent 6b6830ab57
commit f7cf0c65b8
1 changed files with 120 additions and 12 deletions

View File

@ -5,8 +5,11 @@ use ChannelCount;
use BackendSpecificError; use BackendSpecificError;
use BuildStreamError; use BuildStreamError;
use DefaultFormatError; use DefaultFormatError;
use Device as DeviceTrait;
use DeviceNameError; use DeviceNameError;
use EventLoop as EventLoopTrait;
use Format; use Format;
use Host as HostTrait;
use PauseStreamError; use PauseStreamError;
use PlayStreamError; use PlayStreamError;
use SupportedFormatsError; use SupportedFormatsError;
@ -14,6 +17,7 @@ use SampleFormat;
use SampleRate; use SampleRate;
use StreamData; use StreamData;
use StreamDataResult; use StreamDataResult;
use StreamId as StreamIdTrait;
use SupportedFormat; use SupportedFormat;
use UnknownTypeInputBuffer; use UnknownTypeInputBuffer;
use UnknownTypeOutputBuffer; use UnknownTypeOutputBuffer;
@ -72,13 +76,117 @@ mod enumerate;
pub use self::enumerate::{Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device}; 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<Self, crate::HostUnavailable> {
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<Self::Devices, DevicesError> {
Devices::new()
}
fn default_input_device(&self) -> Option<Self::Device> {
default_input_device()
}
fn default_output_device(&self) -> Option<Self::Device> {
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<String, DeviceNameError> {
Device::name(self)
}
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
Device::supported_input_formats(self)
}
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
Device::supported_output_formats(self)
}
fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
Device::default_input_format(self)
}
fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
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<Self::StreamId, BuildStreamError> {
EventLoop::build_input_stream(self, device, format)
}
fn build_output_stream(
&self,
device: &Self::Device,
format: &Format,
) -> Result<Self::StreamId, BuildStreamError> {
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<F>(&self, callback: F) -> !
where
F: FnMut(Self::StreamId, StreamDataResult) + Send,
{
EventLoop::run(self, callback)
}
}
impl StreamIdTrait for StreamId {}
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct Device { pub struct Device {
audio_device_id: AudioDeviceID, audio_device_id: AudioDeviceID,
} }
impl Device { impl Device {
pub fn name(&self) -> Result<String, DeviceNameError> { fn name(&self) -> Result<String, DeviceNameError> {
let property_address = AudioObjectPropertyAddress { let property_address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyDeviceNameCFString, mSelector: kAudioDevicePropertyDeviceNameCFString,
mScope: kAudioDevicePropertyScopeOutput, mScope: kAudioDevicePropertyScopeOutput,
@ -212,11 +320,11 @@ impl Device {
} }
} }
pub fn supported_input_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> { fn supported_input_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> {
self.supported_formats(kAudioObjectPropertyScopeInput) self.supported_formats(kAudioObjectPropertyScopeInput)
} }
pub fn supported_output_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> { fn supported_output_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> {
self.supported_formats(kAudioObjectPropertyScopeOutput) self.supported_formats(kAudioObjectPropertyScopeOutput)
} }
@ -296,11 +404,11 @@ impl Device {
} }
} }
pub fn default_input_format(&self) -> Result<Format, DefaultFormatError> { fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
self.default_format(kAudioObjectPropertyScopeInput) self.default_format(kAudioObjectPropertyScopeInput)
} }
pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> { fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
self.default_format(kAudioObjectPropertyScopeOutput) self.default_format(kAudioObjectPropertyScopeOutput)
} }
} }
@ -435,7 +543,7 @@ fn audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, cor
impl EventLoop { impl EventLoop {
#[inline] #[inline]
pub fn new() -> EventLoop { fn new() -> EventLoop {
EventLoop { EventLoop {
user_callback: Arc::new(Mutex::new(UserCallback::Inactive)), user_callback: Arc::new(Mutex::new(UserCallback::Inactive)),
streams: Mutex::new(Vec::new()), streams: Mutex::new(Vec::new()),
@ -443,7 +551,7 @@ impl EventLoop {
} }
#[inline] #[inline]
pub fn run<F>(&self, mut callback: F) -> ! fn run<F>(&self, mut callback: F) -> !
where F: FnMut(StreamId, StreamDataResult) + Send where F: FnMut(StreamId, StreamDataResult) + Send
{ {
{ {
@ -490,7 +598,7 @@ impl EventLoop {
} }
#[inline] #[inline]
pub fn build_input_stream( fn build_input_stream(
&self, &self,
device: &Device, device: &Device,
format: &Format, format: &Format,
@ -712,7 +820,7 @@ impl EventLoop {
} }
#[inline] #[inline]
pub fn build_output_stream( fn build_output_stream(
&self, &self,
device: &Device, device: &Device,
format: &Format, format: &Format,
@ -787,14 +895,14 @@ impl EventLoop {
Ok(StreamId(stream_id)) 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(); let mut streams = self.streams.lock().unwrap();
streams[stream_id.0] = None; 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 mut streams = self.streams.lock().unwrap();
let stream = streams[stream_id.0].as_mut().unwrap(); let stream = streams[stream_id.0].as_mut().unwrap();
@ -809,7 +917,7 @@ impl EventLoop {
Ok(()) 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 mut streams = self.streams.lock().unwrap();
let stream = streams[stream_id.0].as_mut().unwrap(); let stream = streams[stream_id.0].as_mut().unwrap();