audio_device/wasapi/
mod.rs1use std::mem;
4use std::ptr;
5use thiserror::Error;
6use windows::Interface as _;
7use windows_sys::Windows::Win32::Com as com;
8use windows_sys::Windows::Win32::CoreAudio as core;
9
10mod initialized_client;
11pub use self::initialized_client::InitializedClient;
12
13mod client;
14pub use self::client::Client;
15
16mod render_client;
17pub use self::render_client::RenderClient;
18
19mod buffer_mut;
20pub use self::buffer_mut::BufferMut;
21
22mod sample;
23pub use self::sample::Sample;
24
25#[derive(Debug, Error)]
27pub enum Error {
28 #[error("system error: {0}")]
30 Sys(
31 #[from]
32 #[source]
33 windows::Error,
34 ),
35 #[error("Device doesn't support a compatible mix format")]
37 UnsupportedMixFormat,
38}
39
40pub fn audio_prelude() {
42 if let Err(e) = windows::initialize_mta() {
43 panic!("failed to initialize multithreaded apartment: {}", e);
44 }
45}
46
47#[derive(Debug, Clone, Copy)]
49pub enum SampleFormat {
50 I16,
52 F32,
54}
55
56#[derive(Debug, Clone, Copy)]
60pub struct ClientConfig {
61 tag: ste::Tag,
62 pub channels: u16,
64 pub sample_rate: u32,
66 pub sample_format: SampleFormat,
68}
69
70pub fn default_output_client() -> Result<Option<Client>, Error> {
72 let tag = ste::Tag::current_thread();
73
74 let enumerator: core::IMMDeviceEnumerator =
75 windows::create_instance(&core::MMDeviceEnumerator)?;
76
77 let mut device = None;
78
79 unsafe {
80 enumerator
81 .GetDefaultAudioEndpoint(core::EDataFlow::eRender, core::ERole::eConsole, &mut device)
82 .ok()?;
83
84 let device = match device {
85 Some(device) => device,
86 None => return Ok(None),
87 };
88
89 let mut audio_client: mem::MaybeUninit<core::IAudioClient> = mem::MaybeUninit::zeroed();
90
91 device
92 .Activate(
93 &core::IAudioClient::IID,
94 com::CLSCTX::CLSCTX_ALL.0,
95 ptr::null_mut(),
96 audio_client.as_mut_ptr() as *mut _,
97 )
98 .ok()?;
99
100 let audio_client = audio_client.assume_init();
101
102 Ok(Some(Client { tag, audio_client }))
103 }
104}