1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Minimal implementation of interfaces in libcras for external builds.
6 //
7 // These just exist to allow us to build and clippy check the audio feature
8 // when building outside of ChromeOS. When building for ChromeOS, this stub
9 // will be replaced by the actual libcras implementation:
10 // https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/third_party/adhd/cras/client/libcras/
11 //
12 // Any changes to the libcras API used in crosvm needs to be reflected in this
13 // stub as well so as to have a successful crosvm build outside of ChromeOS.
14 //
15 // Instantiating a CrasClient using this will always panic!
16
17 use std::error;
18 use std::fmt;
19 use std::str::FromStr;
20
21 use audio_streams::shm_streams::SharedMemory;
22 use audio_streams::shm_streams::ShmStream;
23 use audio_streams::shm_streams::ShmStreamSource;
24 use audio_streams::BoxError;
25 use audio_streams::SampleFormat;
26 use audio_streams::StreamDirection;
27 use audio_streams::StreamEffect;
28 use audio_streams::StreamSource;
29 use audio_streams::StreamSourceGenerator;
30 use serde::Deserialize;
31 use serde::Deserializer;
32 use serde::Serialize;
33
34 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
35 #[allow(non_camel_case_types)]
36 pub enum CRAS_CLIENT_TYPE {
37 #[serde(rename = "arcvm")]
38 CRAS_CLIENT_TYPE_ARCVM,
39 #[serde(rename = "crosvm")]
40 CRAS_CLIENT_TYPE_CROSVM,
41 }
42
43 pub type CrasClientType = CRAS_CLIENT_TYPE;
44
45 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
46 #[allow(non_camel_case_types)]
47 pub enum CRAS_STREAM_TYPE {
48 #[serde(rename = "default")]
49 CRAS_STREAM_TYPE_DEFAULT,
50 #[serde(rename = "pro_audio")]
51 CRAS_STREAM_TYPE_PRO_AUDIO,
52 }
53
54 pub type CrasStreamType = CRAS_STREAM_TYPE;
55
56 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
57 #[serde(rename_all = "lowercase")]
58 pub enum CrasSocketType {
59 Legacy,
60 Unified,
61 }
62
63 #[derive(Debug)]
64 pub enum Error {
65 InvalidClientType,
66 InvalidSocketType,
67 }
68 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 write!(f, "")
71 }
72 }
73
74 impl error::Error for Error {}
75
76 pub type CrasSysError = Error;
77
78 impl FromStr for CrasClientType {
79 type Err = CrasSysError;
from_str(cras_type: &str) -> std::result::Result<Self, Self::Err>80 fn from_str(cras_type: &str) -> std::result::Result<Self, Self::Err> {
81 match cras_type {
82 "crosvm" => Ok(CrasClientType::CRAS_CLIENT_TYPE_CROSVM),
83 "arcvm" => Ok(CrasClientType::CRAS_CLIENT_TYPE_ARCVM),
84 _ => Err(Error::InvalidClientType),
85 }
86 }
87 }
88
89 impl FromStr for CrasSocketType {
90 type Err = Error;
from_str(sock_type: &str) -> std::result::Result<Self, Self::Err>91 fn from_str(sock_type: &str) -> std::result::Result<Self, Self::Err> {
92 match sock_type {
93 "legacy" => Ok(CrasSocketType::Legacy),
94 "unified" => Ok(CrasSocketType::Unified),
95 _ => Err(Error::InvalidSocketType),
96 }
97 }
98 }
99
100 pub struct CrasStreamSourceGenerator {}
101
102 impl CrasStreamSourceGenerator {
new(_capture: bool, _client_type: CrasClientType, _socket_type: CrasSocketType) -> Self103 pub fn new(_capture: bool, _client_type: CrasClientType, _socket_type: CrasSocketType) -> Self {
104 panic!("Cannot create cras audio device on non-chromeos crosvm builds.")
105 }
106
with_stream_type( _capture: bool, _client_type: CrasClientType, _socket_type: CrasSocketType, _stream_type: CrasStreamType, ) -> Self107 pub fn with_stream_type(
108 _capture: bool,
109 _client_type: CrasClientType,
110 _socket_type: CrasSocketType,
111 _stream_type: CrasStreamType,
112 ) -> Self {
113 panic!("Cannot create cras audio device on non-chromeos crosvm builds.")
114 }
115 }
116
117 impl StreamSourceGenerator for CrasStreamSourceGenerator {
generate(&self) -> std::result::Result<Box<dyn StreamSource>, BoxError>118 fn generate(&self) -> std::result::Result<Box<dyn StreamSource>, BoxError> {
119 panic!("Cannot create cras audio device on non-chromeos crosvm builds.")
120 }
121 }
122
deserialize_cras_client_type<'de, D: Deserializer<'de>>( deserializer: D, ) -> std::result::Result<CRAS_CLIENT_TYPE, D::Error>123 pub fn deserialize_cras_client_type<'de, D: Deserializer<'de>>(
124 deserializer: D,
125 ) -> std::result::Result<CRAS_CLIENT_TYPE, D::Error> {
126 let s = String::deserialize(deserializer)?;
127
128 match s.parse() {
129 Ok(client_type) => Ok(client_type),
130 Err(e) => Err(serde::de::Error::custom(e.to_string())),
131 }
132 }
133
134 type Result<T> = std::result::Result<T, Error>;
135
136 pub struct CrasClient {}
137 impl CrasClient {
with_type(_: CrasSocketType) -> Result<Self>138 pub fn with_type(_: CrasSocketType) -> Result<Self> {
139 panic!("Cannot create cras audio device on non-chromeos crosvm builds.")
140 }
set_client_type(&mut self, _: CrasClientType)141 pub fn set_client_type(&mut self, _: CrasClientType) {}
enable_cras_capture(&mut self)142 pub fn enable_cras_capture(&mut self) {}
143 }
144
145 impl<E: std::error::Error> ShmStreamSource<E> for CrasClient {
new_stream( &mut self, _direction: StreamDirection, _num_channels: usize, _format: SampleFormat, _frame_rate: u32, _buffer_size: usize, _effects: &[StreamEffect], _client_shm: &dyn SharedMemory<Error = E>, _buffer_offsets: [u64; 2], ) -> std::result::Result<Box<dyn ShmStream>, BoxError>146 fn new_stream(
147 &mut self,
148 _direction: StreamDirection,
149 _num_channels: usize,
150 _format: SampleFormat,
151 _frame_rate: u32,
152 _buffer_size: usize,
153 _effects: &[StreamEffect],
154 _client_shm: &dyn SharedMemory<Error = E>,
155 _buffer_offsets: [u64; 2],
156 ) -> std::result::Result<Box<dyn ShmStream>, BoxError> {
157 panic!("Cannot create cras audio device on non-chromeos crosvm builds.")
158 }
159 }
160