Implement `Host` API for coreaudio backend
This commit is contained in:
parent
6b6830ab57
commit
f7cf0c65b8
|
@ -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<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)]
|
||||
pub struct Device {
|
||||
audio_device_id: AudioDeviceID,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn name(&self) -> Result<String, DeviceNameError> {
|
||||
fn name(&self) -> Result<String, DeviceNameError> {
|
||||
let property_address = AudioObjectPropertyAddress {
|
||||
mSelector: kAudioDevicePropertyDeviceNameCFString,
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn supported_output_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> {
|
||||
fn supported_output_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
||||
fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
||||
self.default_format(kAudioObjectPropertyScopeOutput)
|
||||
}
|
||||
}
|
||||
|
@ -435,7 +543,7 @@ fn audio_unit_from_device(device: &Device, input: bool) -> Result<AudioUnit, cor
|
|||
|
||||
impl EventLoop {
|
||||
#[inline]
|
||||
pub fn new() -> 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<F>(&self, mut callback: F) -> !
|
||||
fn run<F>(&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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue