audio_device/alsa/
async_writer.rs1use crate::alsa::{Error, Pcm, Result};
2use crate::libc as c;
3use crate::unix::errno;
4use crate::unix::poll;
5use crate::unix::AsyncPoll;
6use audio_core as core;
7use std::marker;
8
9pub struct AsyncWriter<'a, T> {
13 pcm: &'a mut Pcm,
14 poll_handle: AsyncPoll,
15 pollfd: c::pollfd,
16 channels: usize,
17 _marker: marker::PhantomData<T>,
18}
19
20impl<'a, T> AsyncWriter<'a, T> {
21 pub(super) unsafe fn new(pcm: &'a mut Pcm, pollfd: c::pollfd, channels: usize) -> Result<Self> {
28 Ok(Self {
29 pcm,
30 poll_handle: AsyncPoll::new(pollfd)?,
31 pollfd,
32 channels,
33 _marker: marker::PhantomData,
34 })
35 }
36
37 pub async fn write_interleaved<B>(&mut self, mut buf: B) -> Result<()>
39 where
40 B: core::ReadBuf + core::ExactSizeBuf + core::AsInterleaved<T>,
41 {
42 if buf.channels() != self.channels {
43 return Err(Error::ChannelsMismatch {
44 actual: buf.channels(),
45 expected: self.channels,
46 });
47 }
48
49 while buf.has_remaining() {
50 self.pcm.tag.ensure_on_thread();
51 let frames = buf.frames() as usize;
52
53 unsafe {
54 let result = {
55 let ptr = buf.as_interleaved().as_ptr() as *const c::c_void;
56 self.pcm.write_interleaved_unchecked(ptr, frames as u64)
57 };
58
59 let written = match result {
60 Ok(written) => written as usize,
61 Err(Error::Sys(errno::EWOULDBLOCK)) => {
62 loop {
63 let guard = self.poll_handle.returned_events().await;
64 self.pollfd.revents = guard.events();
65
66 let mut fds = [self.pollfd];
67 let flags = self.pcm.poll_descriptors_revents(&mut fds)?;
68
69 if flags == poll::PollFlags::POLLOUT {
70 break;
71 }
72
73 drop(guard);
74 }
75
76 continue;
77 }
78 Err(e) => return Err(e),
79 };
80
81 buf.advance(written);
82 }
83 }
84
85 Ok(())
86 }
87}
88
89unsafe impl<T> Send for AsyncWriter<'_, T> {}