devices/virtio/snd/sys/
linux.rs1#[cfg(feature = "audio_aaudio")]
6use android_audio::AndroidAudioStreamSourceGenerator;
7use async_trait::async_trait;
8use audio_streams::capture::AsyncCaptureBuffer;
9use audio_streams::capture::AsyncCaptureBufferStream;
10use audio_streams::AsyncPlaybackBufferStream;
11use audio_streams::BoxError;
12use audio_streams::StreamSource;
13use audio_streams::StreamSourceGenerator;
14#[cfg(feature = "audio_cras")]
15use base::error;
16use base::set_rt_prio_limit;
17use base::set_rt_round_robin;
18use cros_async::Executor;
19use futures::channel::mpsc::UnboundedSender;
20#[cfg(feature = "audio_cras")]
21use libcras::CrasStreamSourceGenerator;
22#[cfg(feature = "audio_cras")]
23use libcras::CrasStreamType;
24use serde::Deserialize;
25use serde::Serialize;
26
27use crate::virtio::snd::common_backend::async_funcs::CaptureBufferReader;
28use crate::virtio::snd::common_backend::async_funcs::PlaybackBufferWriter;
29use crate::virtio::snd::common_backend::stream_info::StreamInfo;
30use crate::virtio::snd::common_backend::DirectionalStream;
31use crate::virtio::snd::common_backend::Error;
32use crate::virtio::snd::common_backend::PcmResponse;
33use crate::virtio::snd::common_backend::SndData;
34use crate::virtio::snd::parameters::Error as ParametersError;
35use crate::virtio::snd::parameters::Parameters;
36
37const AUDIO_THREAD_RTPRIO: u16 = 10; pub(crate) type SysAudioStreamSourceGenerator = Box<dyn StreamSourceGenerator>;
40pub(crate) type SysAudioStreamSource = Box<dyn StreamSource>;
41pub(crate) type SysBufferReader = UnixBufferReader;
42
43pub struct SysDirectionOutput {
44 pub async_playback_buffer_stream: Box<dyn audio_streams::AsyncPlaybackBufferStream>,
45 pub buffer_writer: Box<dyn PlaybackBufferWriter>,
46}
47
48pub(crate) struct SysAsyncStreamObjects {
49 pub(crate) stream: DirectionalStream,
50 pub(crate) pcm_sender: UnboundedSender<PcmResponse>,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
54pub enum StreamSourceBackend {
55 #[cfg(feature = "audio_aaudio")]
56 AAUDIO,
57 #[cfg(feature = "audio_cras")]
58 CRAS,
59}
60
61impl From<StreamSourceBackend> for String {
63 fn from(backend: StreamSourceBackend) -> Self {
64 match backend {
65 #[cfg(feature = "audio_aaudio")]
66 StreamSourceBackend::AAUDIO => "aaudio".to_owned(),
67 #[cfg(feature = "audio_cras")]
68 StreamSourceBackend::CRAS => "cras".to_owned(),
69 }
70 }
71}
72
73impl TryFrom<&str> for StreamSourceBackend {
74 type Error = ParametersError;
75
76 fn try_from(s: &str) -> Result<Self, Self::Error> {
77 match s {
78 #[cfg(feature = "audio_aaudio")]
79 "aaudio" => Ok(StreamSourceBackend::AAUDIO),
80 #[cfg(feature = "audio_cras")]
81 "cras" => Ok(StreamSourceBackend::CRAS),
82 _ => Err(ParametersError::InvalidBackend),
83 }
84 }
85}
86
87#[cfg(feature = "audio_aaudio")]
88pub(crate) fn create_aaudio_stream_source_generators(
89 snd_data: &SndData,
90) -> Vec<SysAudioStreamSourceGenerator> {
91 let mut generators: Vec<Box<dyn StreamSourceGenerator>> =
92 Vec::with_capacity(snd_data.pcm_info_len());
93 for pcm_info in snd_data.pcm_info_iter() {
94 assert_eq!(pcm_info.features, 0); generators.push(Box::new(AndroidAudioStreamSourceGenerator::new()));
96 }
97 generators
98}
99
100#[cfg(feature = "audio_cras")]
101pub(crate) fn create_cras_stream_source_generators(
102 params: &Parameters,
103 snd_data: &SndData,
104) -> Vec<Box<dyn StreamSourceGenerator>> {
105 let mut generators: Vec<Box<dyn StreamSourceGenerator>> =
106 Vec::with_capacity(snd_data.pcm_info_len());
107 for pcm_info in snd_data.pcm_info_iter() {
108 let device_params = params.get_device_params(pcm_info).unwrap_or_else(|err| {
109 error!("Create cras stream source generator error: {}", err);
110 Default::default()
111 });
112 generators.push(Box::new(CrasStreamSourceGenerator::with_stream_type(
113 params.capture,
114 device_params.client_type.unwrap_or(params.client_type),
115 params.socket_type,
116 device_params
117 .stream_type
118 .unwrap_or(CrasStreamType::CRAS_STREAM_TYPE_DEFAULT),
119 )));
120 }
121 generators
122}
123
124#[allow(unused_variables)]
125pub(crate) fn create_stream_source_generators(
126 backend: StreamSourceBackend,
127 params: &Parameters,
128 snd_data: &SndData,
129) -> Vec<Box<dyn StreamSourceGenerator>> {
130 match backend {
131 #[cfg(feature = "audio_aaudio")]
132 StreamSourceBackend::AAUDIO => create_aaudio_stream_source_generators(snd_data),
133 #[cfg(feature = "audio_cras")]
134 StreamSourceBackend::CRAS => create_cras_stream_source_generators(params, snd_data),
135 }
136}
137
138pub(crate) fn set_audio_thread_priority() -> Result<(), base::Error> {
139 set_rt_prio_limit(u64::from(AUDIO_THREAD_RTPRIO))
140 .and_then(|_| set_rt_round_robin(i32::from(AUDIO_THREAD_RTPRIO)))
141}
142
143impl StreamInfo {
144 async fn set_up_async_playback_stream(
151 &mut self,
152 frame_size: usize,
153 ex: &Executor,
154 ) -> Result<Box<dyn AsyncPlaybackBufferStream>, Error> {
155 Ok(self
156 .stream_source
157 .as_mut()
158 .ok_or(Error::EmptyStreamSource)?
159 .async_new_async_playback_stream(
160 self.channels as usize,
161 self.format,
162 self.frame_rate,
163 self.period_bytes / frame_size,
165 ex,
166 )
167 .await
168 .map_err(Error::CreateStream)?
169 .1)
170 }
171
172 pub(crate) async fn set_up_async_capture_stream(
173 &mut self,
174 frame_size: usize,
175 ex: &Executor,
176 ) -> Result<SysBufferReader, Error> {
177 let async_capture_buffer_stream = self
178 .stream_source
179 .as_mut()
180 .ok_or(Error::EmptyStreamSource)?
181 .async_new_async_capture_stream(
182 self.channels as usize,
183 self.format,
184 self.frame_rate,
185 self.period_bytes / frame_size,
186 &self.effects,
187 ex,
188 )
189 .await
190 .map_err(Error::CreateStream)?
191 .1;
192 Ok(SysBufferReader::new(async_capture_buffer_stream))
193 }
194
195 pub(crate) async fn create_directionstream_output(
196 &mut self,
197 frame_size: usize,
198 ex: &Executor,
199 ) -> Result<DirectionalStream, Error> {
200 let async_playback_buffer_stream =
201 self.set_up_async_playback_stream(frame_size, ex).await?;
202
203 let buffer_writer = UnixBufferWriter::new(self.period_bytes);
204
205 Ok(DirectionalStream::Output(SysDirectionOutput {
206 async_playback_buffer_stream,
207 buffer_writer: Box::new(buffer_writer),
208 }))
209 }
210}
211
212pub(crate) struct UnixBufferReader {
213 async_stream: Box<dyn AsyncCaptureBufferStream>,
214}
215
216impl UnixBufferReader {
217 fn new(async_stream: Box<dyn AsyncCaptureBufferStream>) -> Self
218 where
219 Self: Sized,
220 {
221 UnixBufferReader { async_stream }
222 }
223}
224#[async_trait(?Send)]
225impl CaptureBufferReader for UnixBufferReader {
226 async fn get_next_capture_period(
227 &mut self,
228 ex: &Executor,
229 ) -> Result<AsyncCaptureBuffer, BoxError> {
230 Ok(self
231 .async_stream
232 .next_capture_buffer(ex)
233 .await
234 .map_err(Error::FetchBuffer)?)
235 }
236}
237
238pub(crate) struct UnixBufferWriter {
239 guest_period_bytes: usize,
240}
241
242#[async_trait(?Send)]
243impl PlaybackBufferWriter for UnixBufferWriter {
244 fn new(guest_period_bytes: usize) -> Self {
245 UnixBufferWriter { guest_period_bytes }
246 }
247 fn endpoint_period_bytes(&self) -> usize {
248 self.guest_period_bytes
249 }
250}