audio_device/wasapi/
render_client.rs

1use 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
10/// A typed render client.
11pub 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    /// Get the buffer associated with the render client.
33    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    /// Get access to the raw mutable buffer.
48    ///
49    /// This will block until it is appropriate to submit a buffer.
50    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        /// Get access to the raw mutable buffer.
93        ///
94        /// This will block until it is appropriate to submit a buffer.
95        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
123// Safety: thread safety is ensured through tagging with ste::Tag.
124unsafe impl<T, E> Send for RenderClient<T, E> {}