• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //! Provides an interface for playing and recording audio through CRAS server.
5 //!
6 //! `CrasClient` implements `StreamSource` trait and it can create playback or capture
7 //! stream - `CrasStream` which can be a
8 //! - `PlaybackBufferStream` for audio playback or
9 //! - `CaptureBufferStream` for audio capture.
10 //!
11 //! # Example of file audio playback
12 //!
13 //! `PlaybackBuffer`s to be filled with audio samples are obtained by calling
14 //! `next_playback_buffer` from `CrasStream`.
15 //!
16 //! Users playing audio fill the provided buffers with audio. When a `PlaybackBuffer` is dropped,
17 //! the samples written to it are committed to the `CrasStream` it came from.
18 //!
19 //!
20 //! ```
21 //! // An example of playing raw audio data from a given file
22 //! use std::env;
23 //! use std::fs::File;
24 //! use std::io::{Read, Write};
25 //! use std::thread::{spawn, JoinHandle};
26 //! type Result<T> = std::result::Result<T, Box<std::error::Error>>;
27 //!
28 //! use libcras::{CrasClient, CrasClientType};
29 //! use audio_streams::StreamSource;
30 //!
31 //! const BUFFER_SIZE: usize = 256;
32 //! const FRAME_RATE: usize = 44100;
33 //! const NUM_CHANNELS: usize = 2;
34 //!
35 //! # fn main() -> Result<()> {
36 //! #    let args: Vec<String> = env::args().collect();
37 //! #    match args.len() {
38 //! #        2 => {
39 //!              let mut cras_client = CrasClient::new()?;
40 //!              cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST);
41 //!              let (_control, mut stream) = cras_client
42 //!                  .new_playback_stream(NUM_CHANNELS, FRAME_RATE, BUFFER_SIZE)?;
43 //!
44 //!              // Plays 1000 * BUFFER_SIZE samples from the given file
45 //!              let mut file = File::open(&args[1])?;
46 //!              let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2];
47 //!              for _i in 0..1000 {
48 //!                  // Reads data to local buffer
49 //!                  let _read_count = file.read(&mut local_buffer)?;
50 //!
51 //!                  // Gets writable buffer from stream and
52 //!                  let mut buffer = stream.next_playback_buffer()?;
53 //!                  // Writes data to stream buffer
54 //!                  let _write_frames = buffer.write(&local_buffer)?;
55 //!              }
56 //!              // Stream and client should gracefully be closed out of this scope
57 //! #        }
58 //! #        _ => {
59 //! #            println!("{} /path/to/playback_file.raw", args[0]);
60 //! #        }
61 //! #    };
62 //! #    Ok(())
63 //! # }
64 //! ```
65 //!
66 //! # Example of file audio capture
67 //!
68 //! `CaptureBuffer`s which contain audio samples are obtained by calling
69 //! `next_capture_buffer` from `CrasStream`.
70 //!
71 //! Users get captured audio samples from the provided buffers. When a `CaptureBuffer` is dropped,
72 //! the number of read samples will be committed to the `CrasStream` it came from.
73 //! ```
74 //! use std::env;
75 //! use std::fs::File;
76 //! use std::io::{Read, Write};
77 //! use std::thread::{spawn, JoinHandle};
78 //! type Result<T> = std::result::Result<T, Box<std::error::Error>>;
79 //!
80 //! use libcras::{CrasClient, CrasClientType};
81 //! use audio_streams::StreamSource;
82 //!
83 //! const BUFFER_SIZE: usize = 256;
84 //! const FRAME_RATE: usize = 44100;
85 //! const NUM_CHANNELS: usize = 2;
86 //!
87 //! # fn main() -> Result<()> {
88 //! #    let args: Vec<String> = env::args().collect();
89 //! #    match args.len() {
90 //! #        2 => {
91 //!              let mut cras_client = CrasClient::new()?;
92 //!              cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST);
93 //!              let (_control, mut stream) = cras_client
94 //!                  .new_capture_stream(NUM_CHANNELS, FRAME_RATE, BUFFER_SIZE)?;
95 //!
96 //!              // Capture 1000 * BUFFER_SIZE samples to the given file
97 //!              let mut file = File::create(&args[1])?;
98 //!              let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2];
99 //!              for _i in 0..1000 {
100 //!
101 //!                  // Gets readable buffer from stream and
102 //!                  let mut buffer = stream.next_capture_buffer()?;
103 //!                  // Reads data to local buffer
104 //!                  let read_count = buffer.read(&mut local_buffer)?;
105 //!                  // Writes data to file
106 //!                  let _read_frames = file.write(&local_buffer[..read_count])?;
107 //!              }
108 //!              // Stream and client should gracefully be closed out of this scope
109 //! #        }
110 //! #        _ => {
111 //! #            println!("{} /path/to/capture_file.raw", args[0]);
112 //! #        }
113 //! #    };
114 //! #    Ok(())
115 //! # }
116 //! ```
117 use std::io;
118 use std::mem;
119 use std::os::unix::{
120     io::{AsRawFd, RawFd},
121     net::UnixStream,
122 };
123 use std::{error, fmt};
124 
125 use audio_streams::{
126     capture::{CaptureBufferStream, DummyCaptureStream},
127     BufferDrop, DummyStreamControl, PlaybackBufferStream, StreamControl, StreamSource,
128 };
129 pub use cras_sys::gen::CRAS_CLIENT_TYPE as CrasClientType;
130 use cras_sys::gen::*;
131 use sys_util::{PollContext, PollToken};
132 
133 mod audio_socket;
134 use crate::audio_socket::AudioSocket;
135 mod cras_server_socket;
136 use crate::cras_server_socket::CrasServerSocket;
137 mod cras_shm;
138 mod cras_stream;
139 use crate::cras_stream::{CrasCaptureData, CrasPlaybackData, CrasStream, CrasStreamData};
140 mod cras_client_message;
141 use crate::cras_client_message::*;
142 
143 #[derive(Debug)]
144 pub enum ErrorType {
145     CrasClientMessageError(cras_client_message::Error),
146     CrasStreamError(cras_stream::Error),
147     IoError(io::Error),
148     SysUtilError(sys_util::Error),
149     MessageTypeError,
150     UnexpectedExit,
151 }
152 
153 #[derive(Debug)]
154 pub struct Error {
155     error_type: ErrorType,
156 }
157 
158 impl Error {
new(error_type: ErrorType) -> Self159     fn new(error_type: ErrorType) -> Self {
160         Self { error_type }
161     }
162 }
163 
164 impl error::Error for Error {}
165 
166 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result167     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168         match self.error_type {
169             ErrorType::CrasClientMessageError(ref err) => err.fmt(f),
170             ErrorType::CrasStreamError(ref err) => err.fmt(f),
171             ErrorType::IoError(ref err) => err.fmt(f),
172             ErrorType::SysUtilError(ref err) => err.fmt(f),
173             ErrorType::MessageTypeError => write!(f, "Message type error"),
174             ErrorType::UnexpectedExit => write!(f, "Unexpected exit"),
175         }
176     }
177 }
178 
179 type Result<T> = std::result::Result<T, Error>;
180 
181 impl From<io::Error> for Error {
from(io_err: io::Error) -> Self182     fn from(io_err: io::Error) -> Self {
183         Self::new(ErrorType::IoError(io_err))
184     }
185 }
186 
187 impl From<sys_util::Error> for Error {
from(sys_util_err: sys_util::Error) -> Self188     fn from(sys_util_err: sys_util::Error) -> Self {
189         Self::new(ErrorType::SysUtilError(sys_util_err))
190     }
191 }
192 
193 impl From<cras_stream::Error> for Error {
from(err: cras_stream::Error) -> Self194     fn from(err: cras_stream::Error) -> Self {
195         Self::new(ErrorType::CrasStreamError(err))
196     }
197 }
198 
199 impl From<cras_client_message::Error> for Error {
from(err: cras_client_message::Error) -> Self200     fn from(err: cras_client_message::Error) -> Self {
201         Self::new(ErrorType::CrasClientMessageError(err))
202     }
203 }
204 
205 /// A CRAS server client, which implements StreamSource. It can create audio streams connecting
206 /// to CRAS server.
207 pub struct CrasClient {
208     server_socket: CrasServerSocket,
209     client_id: u32,
210     next_stream_id: u32,
211     cras_capture: bool,
212     client_type: CRAS_CLIENT_TYPE,
213 }
214 
215 impl CrasClient {
216     /// Blocks creating a `CrasClient` with registered `client_id`
217     ///
218     /// # Results
219     ///
220     /// * `CrasClient` - A client to interact with CRAS server
221     ///
222     /// # Errors
223     ///
224     /// Returns error if error occurs while handling server message or message
225     /// type is incorrect
new() -> Result<Self>226     pub fn new() -> Result<Self> {
227         // Create a connection to the server.
228         let mut server_socket = CrasServerSocket::new()?;
229 
230         // Gets client ID from server
231         let client_id = {
232             match CrasClient::wait_for_message(&mut server_socket)? {
233                 ServerResult::Connected(res, _server_state_fd) => res as u32,
234                 _ => {
235                     return Err(Error::new(ErrorType::MessageTypeError));
236                 }
237             }
238         };
239 
240         Ok(Self {
241             server_socket,
242             client_id,
243             next_stream_id: 0,
244             cras_capture: false,
245             client_type: CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_UNKNOWN,
246         })
247     }
248 
249     /// Enables capturing audio through CRAS server.
enable_cras_capture(&mut self)250     pub fn enable_cras_capture(&mut self) {
251         self.cras_capture = true;
252     }
253 
254     /// Set the type of this client to report to CRAS when connecting streams.
set_client_type(&mut self, client_type: CRAS_CLIENT_TYPE)255     pub fn set_client_type(&mut self, client_type: CRAS_CLIENT_TYPE) {
256         self.client_type = client_type;
257     }
258 
259     // Gets next server_stream_id from client and increment stream_id counter.
next_server_stream_id(&mut self) -> Result<u32>260     fn next_server_stream_id(&mut self) -> Result<u32> {
261         let res = self.next_stream_id;
262         self.next_stream_id += 1;
263         self.server_stream_id(&res)
264     }
265 
266     // Gets server_stream_id from given stream_id
server_stream_id(&self, stream_id: &u32) -> Result<u32>267     fn server_stream_id(&self, stream_id: &u32) -> Result<u32> {
268         Ok((self.client_id << 16) | stream_id)
269     }
270 
271     // Creates general stream with given parameters
create_stream<'a, T: BufferDrop + CrasStreamData<'a>>( &mut self, block_size: u32, direction: CRAS_STREAM_DIRECTION, rate: usize, channel_num: usize, format: snd_pcm_format_t, ) -> Result<CrasStream<'a, T>>272     fn create_stream<'a, T: BufferDrop + CrasStreamData<'a>>(
273         &mut self,
274         block_size: u32,
275         direction: CRAS_STREAM_DIRECTION,
276         rate: usize,
277         channel_num: usize,
278         format: snd_pcm_format_t,
279     ) -> Result<CrasStream<'a, T>> {
280         let stream_id = self.next_server_stream_id()?;
281 
282         // Prepares server message
283         let audio_format = cras_audio_format_packed::new(format, rate, channel_num);
284         let msg_header = cras_server_message {
285             length: mem::size_of::<cras_connect_message>() as u32,
286             id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM,
287         };
288         let server_cmsg = cras_connect_message {
289             header: msg_header,
290             proto_version: CRAS_PROTO_VER,
291             direction,
292             stream_id,
293             stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT,
294             buffer_frames: block_size,
295             cb_threshold: block_size,
296             flags: 0,
297             format: audio_format,
298             dev_idx: CRAS_SPECIAL_DEVICE::NO_DEVICE as u32,
299             effects: 0,
300             client_type: self.client_type,
301             client_shm_size: 0,
302         };
303 
304         // Creates AudioSocket pair
305         let (sock1, sock2) = UnixStream::pair()?;
306 
307         // Sends `CRAS_SERVER_CONNECT_STREAM` message
308         let socks = [sock2.as_raw_fd()];
309         self.server_socket
310             .send_server_message_with_fds(&server_cmsg, &socks)?;
311 
312         let audio_socket = AudioSocket::new(sock1);
313         let mut stream = CrasStream::new(
314             stream_id,
315             self.server_socket.try_clone()?,
316             block_size,
317             direction,
318             rate,
319             channel_num,
320             format,
321             audio_socket,
322         );
323 
324         loop {
325             let result = CrasClient::wait_for_message(&mut self.server_socket)?;
326             if let ServerResult::StreamConnected(_stream_id, header_fd, samples_fd) = result {
327                 stream.init_shm(header_fd, samples_fd)?;
328                 break;
329             }
330         }
331 
332         Ok(stream)
333     }
334 
335     // Blocks handling the first server message received from `socket`.
wait_for_message(socket: &mut CrasServerSocket) -> Result<ServerResult>336     fn wait_for_message(socket: &mut CrasServerSocket) -> Result<ServerResult> {
337         #[derive(PollToken)]
338         enum Token {
339             ServerMsg,
340         }
341         let poll_ctx: PollContext<Token> =
342             PollContext::new().and_then(|pc| pc.add(socket, Token::ServerMsg).and(Ok(pc)))?;
343 
344         let events = poll_ctx.wait()?;
345         // Check the first readable message
346         let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect();
347         tokens
348             .get(0)
349             .ok_or_else(|| Error::new(ErrorType::UnexpectedExit))
350             .and_then(|ref token| {
351                 match token {
352                     Token::ServerMsg => ServerResult::handle_server_message(socket),
353                 }
354                 .map_err(Into::into)
355             })
356     }
357 }
358 
359 impl StreamSource for CrasClient {
new_playback_stream( &mut self, num_channels: usize, frame_rate: usize, buffer_size: usize, ) -> std::result::Result< (Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>, >360     fn new_playback_stream(
361         &mut self,
362         num_channels: usize,
363         frame_rate: usize,
364         buffer_size: usize,
365     ) -> std::result::Result<
366         (Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>),
367         Box<dyn error::Error>,
368     > {
369         Ok((
370             Box::new(DummyStreamControl::new()),
371             Box::new(self.create_stream::<CrasPlaybackData>(
372                 buffer_size as u32,
373                 CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT,
374                 frame_rate,
375                 num_channels,
376                 _snd_pcm_format::SND_PCM_FORMAT_S16_LE,
377             )?),
378         ))
379     }
380 
new_capture_stream( &mut self, num_channels: usize, frame_rate: usize, buffer_size: usize, ) -> std::result::Result< (Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), Box<dyn error::Error>, >381     fn new_capture_stream(
382         &mut self,
383         num_channels: usize,
384         frame_rate: usize,
385         buffer_size: usize,
386     ) -> std::result::Result<
387         (Box<dyn StreamControl>, Box<dyn CaptureBufferStream>),
388         Box<dyn error::Error>,
389     > {
390         if self.cras_capture {
391             Ok((
392                 Box::new(DummyStreamControl::new()),
393                 Box::new(self.create_stream::<CrasCaptureData>(
394                     buffer_size as u32,
395                     CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT,
396                     frame_rate,
397                     num_channels,
398                     _snd_pcm_format::SND_PCM_FORMAT_S16_LE,
399                 )?),
400             ))
401         } else {
402             Ok((
403                 Box::new(DummyStreamControl::new()),
404                 Box::new(DummyCaptureStream::new(
405                     num_channels,
406                     frame_rate,
407                     buffer_size,
408                 )),
409             ))
410         }
411     }
412 
keep_fds(&self) -> Option<Vec<RawFd>>413     fn keep_fds(&self) -> Option<Vec<RawFd>> {
414         Some(vec![self.server_socket.as_raw_fd()])
415     }
416 }
417