audio_device/wasapi/
render_client.rs1use crate::loom::sync::Arc;
2use crate::wasapi::{BufferMut, Error};
3use crate::windows::{Event, RawEvent};
4use std::marker;
5use std::mem;
6use windows_sys::Windows::Win32::CoreAudio as core;
7use windows_sys::Windows::Win32::SystemServices as ss;
8use windows_sys::Windows::Win32::WindowsProgramming as wp;
9
10pub struct RenderClient<T, E> {
12 pub(super) tag: ste::Tag,
13 pub(super) audio_client: core::IAudioClient,
14 pub(super) render_client: core::IAudioRenderClient,
15 pub(super) buffer_size: u32,
16 pub(super) channels: usize,
17 pub(super) event: Arc<E>,
18 pub(super) _marker: marker::PhantomData<T>,
19}
20
21impl<T, E> RenderClient<T, E> {
22 fn get_current_padding(&self) -> Result<u32, Error> {
23 unsafe {
24 let mut padding = mem::MaybeUninit::uninit();
25 self.audio_client
26 .GetCurrentPadding(padding.as_mut_ptr())
27 .ok()?;
28 Ok(padding.assume_init())
29 }
30 }
31
32 fn get_buffer(&self, frames: u32) -> Result<*mut T, Error> {
34 unsafe {
35 let mut data = mem::MaybeUninit::uninit();
36
37 self.render_client
38 .GetBuffer(frames, data.as_mut_ptr())
39 .ok()?;
40
41 Ok(data.assume_init() as *mut T)
42 }
43 }
44}
45
46impl<T> RenderClient<T, Event> {
47 pub fn buffer_mut(&mut self) -> Result<BufferMut<'_, T>, Error> {
51 self.tag.ensure_on_thread();
52
53 unsafe {
54 loop {
55 match ss::WaitForSingleObject(self.event.raw_event(), wp::INFINITE) {
56 ss::WAIT_RETURN_CAUSE::WAIT_OBJECT_0 => (),
57 _ => {
58 return Err(Error::from(windows::Error::new(
59 windows::HRESULT::from_thread(),
60 "waiting for event failed",
61 )));
62 }
63 }
64
65 let padding = self.get_current_padding()?;
66 let frames = self.buffer_size.saturating_sub(padding);
67
68 if frames == 0 {
69 continue;
70 }
71
72 let data = self.get_buffer(frames)?;
73
74 return Ok(BufferMut {
75 tag: self.tag,
76 render_client: &mut self.render_client,
77 data,
78 frames,
79 len: frames as usize * self.channels,
80 in_use: true,
81 _marker: marker::PhantomData,
82 });
83 }
84 }
85 }
86}
87
88cfg_events_driver! {
89 use crate::windows::AsyncEvent;
90
91 impl<T> RenderClient<T, AsyncEvent> {
92 pub async fn buffer_mut_async(&mut self) -> Result<BufferMut<'_, T>, Error> {
96 loop {
97 self.event.wait().await;
98 self.tag.ensure_on_thread();
99
100 let padding = self.get_current_padding()?;
101 let frames = self.buffer_size.saturating_sub(padding);
102
103 if frames == 0 {
104 continue;
105 }
106
107 let data = self.get_buffer(frames)?;
108
109 return Ok(BufferMut {
110 tag: self.tag,
111 render_client: &mut self.render_client,
112 data,
113 frames,
114 len: frames as usize * self.channels,
115 in_use: true,
116 _marker: marker::PhantomData,
117 });
118 }
119 }
120 }
121}
122
123unsafe impl<T, E> Send for RenderClient<T, E> {}