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, BoxError>; 27 //! 28 //! use libcras::{BoxError, CrasClient, CrasClientType}; 29 //! use audio_streams::{SampleFormat, StreamSource}; 30 //! 31 //! const BUFFER_SIZE: usize = 256; 32 //! const FRAME_RATE: u32 = 44100; 33 //! const NUM_CHANNELS: usize = 2; 34 //! const FORMAT: SampleFormat = SampleFormat::S16LE; 35 //! 36 //! # fn main() -> Result<()> { 37 //! # let args: Vec<String> = env::args().collect(); 38 //! # match args.len() { 39 //! # 2 => { 40 //! let mut cras_client = CrasClient::new()?; 41 //! cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST); 42 //! let (_control, mut stream) = cras_client 43 //! .new_playback_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?; 44 //! 45 //! // Plays 1000 * BUFFER_SIZE samples from the given file 46 //! let mut file = File::open(&args[1])?; 47 //! let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2]; 48 //! for _i in 0..1000 { 49 //! // Reads data to local buffer 50 //! let _read_count = file.read(&mut local_buffer)?; 51 //! 52 //! // Gets writable buffer from stream and 53 //! let mut buffer = stream.next_playback_buffer()?; 54 //! // Writes data to stream buffer 55 //! let _write_frames = buffer.write(&local_buffer)?; 56 //! } 57 //! // Stream and client should gracefully be closed out of this scope 58 //! # } 59 //! # _ => { 60 //! # println!("{} /path/to/playback_file.raw", args[0]); 61 //! # } 62 //! # }; 63 //! # Ok(()) 64 //! # } 65 //! ``` 66 //! 67 //! # Example of file audio capture 68 //! 69 //! `CaptureBuffer`s which contain audio samples are obtained by calling 70 //! `next_capture_buffer` from `CrasStream`. 71 //! 72 //! Users get captured audio samples from the provided buffers. When a `CaptureBuffer` is dropped, 73 //! the number of read samples will be committed to the `CrasStream` it came from. 74 //! ``` 75 //! use std::env; 76 //! use std::fs::File; 77 //! use std::io::{Read, Write}; 78 //! use std::thread::{spawn, JoinHandle}; 79 //! type Result<T> = std::result::Result<T, BoxError>; 80 //! 81 //! use libcras::{BoxError, CrasClient, CrasClientType}; 82 //! use audio_streams::{SampleFormat, StreamSource}; 83 //! 84 //! const BUFFER_SIZE: usize = 256; 85 //! const FRAME_RATE: u32 = 44100; 86 //! const NUM_CHANNELS: usize = 2; 87 //! const FORMAT: SampleFormat = SampleFormat::S16LE; 88 //! 89 //! # fn main() -> Result<()> { 90 //! # let args: Vec<String> = env::args().collect(); 91 //! # match args.len() { 92 //! # 2 => { 93 //! let mut cras_client = CrasClient::new()?; 94 //! cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST); 95 //! let (_control, mut stream) = cras_client 96 //! .new_capture_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?; 97 //! 98 //! // Capture 1000 * BUFFER_SIZE samples to the given file 99 //! let mut file = File::create(&args[1])?; 100 //! let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2]; 101 //! for _i in 0..1000 { 102 //! 103 //! // Gets readable buffer from stream and 104 //! let mut buffer = stream.next_capture_buffer()?; 105 //! // Reads data to local buffer 106 //! let read_count = buffer.read(&mut local_buffer)?; 107 //! // Writes data to file 108 //! let _read_frames = file.write(&local_buffer[..read_count])?; 109 //! } 110 //! // Stream and client should gracefully be closed out of this scope 111 //! # } 112 //! # _ => { 113 //! # println!("{} /path/to/capture_file.raw", args[0]); 114 //! # } 115 //! # }; 116 //! # Ok(()) 117 //! # } 118 //! ``` 119 use std::io; 120 use std::mem; 121 use std::os::unix::{ 122 io::{AsRawFd, RawFd}, 123 net::UnixStream, 124 }; 125 use std::{error, fmt}; 126 127 pub use audio_streams::BoxError; 128 use audio_streams::{ 129 capture::{CaptureBufferStream, NoopCaptureStream}, 130 shm_streams::{NullShmStream, ShmStream, ShmStreamSource}, 131 BufferDrop, NoopStreamControl, PlaybackBufferStream, SampleFormat, StreamControl, 132 StreamDirection, StreamEffect, StreamSource, 133 }; 134 use cras_sys::gen::*; 135 pub use cras_sys::gen::{ 136 CRAS_CLIENT_TYPE as CrasClientType, CRAS_NODE_TYPE as CrasNodeType, 137 CRAS_STREAM_EFFECT as CrasStreamEffect, 138 }; 139 pub use cras_sys::{AudioDebugInfo, CrasIodevInfo, CrasIonodeInfo, Error as CrasSysError}; 140 use sys_util::{PollContext, PollToken, SharedMemory}; 141 142 mod audio_socket; 143 use crate::audio_socket::AudioSocket; 144 mod cras_server_socket; 145 use crate::cras_server_socket::CrasServerSocket; 146 pub use crate::cras_server_socket::CrasSocketType; 147 mod cras_shm; 148 use crate::cras_shm::CrasServerState; 149 pub mod cras_shm_stream; 150 use crate::cras_shm_stream::CrasShmStream; 151 mod cras_stream; 152 use crate::cras_stream::{CrasCaptureData, CrasPlaybackData, CrasStream, CrasStreamData}; 153 mod cras_client_message; 154 use crate::cras_client_message::*; 155 156 #[derive(Debug)] 157 pub enum Error { 158 CrasClientMessageError(cras_client_message::Error), 159 CrasStreamError(cras_stream::Error), 160 CrasSysError(cras_sys::Error), 161 IoError(io::Error), 162 SysUtilError(sys_util::Error), 163 MessageTypeError, 164 UnexpectedExit, 165 } 166 167 impl error::Error for Error {} 168 169 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 171 match self { 172 Error::CrasClientMessageError(ref err) => err.fmt(f), 173 Error::CrasStreamError(ref err) => err.fmt(f), 174 Error::CrasSysError(ref err) => err.fmt(f), 175 Error::IoError(ref err) => err.fmt(f), 176 Error::SysUtilError(ref err) => err.fmt(f), 177 Error::MessageTypeError => write!(f, "Message type error"), 178 Error::UnexpectedExit => write!(f, "Unexpected exit"), 179 } 180 } 181 } 182 183 type Result<T> = std::result::Result<T, Error>; 184 185 impl From<io::Error> for Error { from(io_err: io::Error) -> Self186 fn from(io_err: io::Error) -> Self { 187 Error::IoError(io_err) 188 } 189 } 190 191 impl From<sys_util::Error> for Error { from(sys_util_err: sys_util::Error) -> Self192 fn from(sys_util_err: sys_util::Error) -> Self { 193 Error::SysUtilError(sys_util_err) 194 } 195 } 196 197 impl From<cras_stream::Error> for Error { from(err: cras_stream::Error) -> Self198 fn from(err: cras_stream::Error) -> Self { 199 Error::CrasStreamError(err) 200 } 201 } 202 203 impl From<cras_client_message::Error> for Error { from(err: cras_client_message::Error) -> Self204 fn from(err: cras_client_message::Error) -> Self { 205 Error::CrasClientMessageError(err) 206 } 207 } 208 209 /// A CRAS server client, which implements StreamSource and ShmStreamSource. 210 /// It can create audio streams connecting to CRAS server. 211 pub struct CrasClient<'a> { 212 server_socket: CrasServerSocket, 213 server_state: CrasServerState<'a>, 214 client_id: u32, 215 next_stream_id: u32, 216 cras_capture: bool, 217 client_type: CRAS_CLIENT_TYPE, 218 } 219 220 impl<'a> CrasClient<'a> { 221 /// Blocks creating a `CrasClient` with registered `client_id` 222 /// 223 /// # Results 224 /// 225 /// * `CrasClient` - A client to interact with CRAS server 226 /// 227 /// # Errors 228 /// 229 /// Returns error if error occurs while handling server message or message 230 /// type is incorrect new() -> Result<Self>231 pub fn new() -> Result<Self> { 232 Self::with_type(CrasSocketType::Legacy) 233 } 234 235 /// Tries to create a `CrasClient` with a given `CrasSocketType`. 236 /// 237 /// # Errors 238 /// 239 /// Returns error if error occurs while handling server message or message 240 /// type is incorrect. with_type(socket_type: CrasSocketType) -> Result<Self>241 pub fn with_type(socket_type: CrasSocketType) -> Result<Self> { 242 // Create a connection to the server. 243 let mut server_socket = CrasServerSocket::with_type(socket_type)?; 244 // Gets client ID and server state fd from server 245 if let ServerResult::Connected(client_id, server_state_fd) = 246 CrasClient::wait_for_message(&mut server_socket)? 247 { 248 Ok(Self { 249 server_socket, 250 server_state: CrasServerState::try_new(server_state_fd)?, 251 client_id, 252 next_stream_id: 0, 253 cras_capture: false, 254 client_type: CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_UNKNOWN, 255 }) 256 } else { 257 Err(Error::MessageTypeError) 258 } 259 } 260 261 /// Enables capturing audio through CRAS server. enable_cras_capture(&mut self)262 pub fn enable_cras_capture(&mut self) { 263 self.cras_capture = true; 264 } 265 266 /// Set the type of this client to report to CRAS when connecting streams. set_client_type(&mut self, client_type: CRAS_CLIENT_TYPE)267 pub fn set_client_type(&mut self, client_type: CRAS_CLIENT_TYPE) { 268 self.client_type = client_type; 269 } 270 271 /// Sets the system volume to `volume`. 272 /// 273 /// Send a message to the server to request setting the system volume 274 /// to `volume`. No response is returned from the server. 275 /// 276 /// # Errors 277 /// 278 /// If writing the message to the server socket failed. set_system_volume(&mut self, volume: u32) -> Result<()>279 pub fn set_system_volume(&mut self, volume: u32) -> Result<()> { 280 let header = cras_server_message { 281 length: mem::size_of::<cras_set_system_volume>() as u32, 282 id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_VOLUME, 283 }; 284 let msg = cras_set_system_volume { header, volume }; 285 286 self.server_socket.send_server_message_with_fds(&msg, &[])?; 287 Ok(()) 288 } 289 290 /// Sets the system mute status to `mute`. 291 /// 292 /// Send a message to the server to request setting the system mute 293 /// to `mute`. No response is returned from the server. 294 /// 295 /// # Errors 296 /// 297 /// If writing the message to the server socket failed. set_system_mute(&mut self, mute: bool) -> Result<()>298 pub fn set_system_mute(&mut self, mute: bool) -> Result<()> { 299 let header = cras_server_message { 300 length: mem::size_of::<cras_set_system_mute>() as u32, 301 id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_MUTE, 302 }; 303 let msg = cras_set_system_mute { 304 header, 305 mute: mute as i32, 306 }; 307 308 self.server_socket.send_server_message_with_fds(&msg, &[])?; 309 Ok(()) 310 } 311 312 /// Gets the system volume. 313 /// 314 /// Read the current value for system volume from the server shared memory. get_system_volume(&self) -> u32315 pub fn get_system_volume(&self) -> u32 { 316 self.server_state.get_system_volume() 317 } 318 319 /// Gets the system mute. 320 /// 321 /// Read the current value for system mute from the server shared memory. get_system_mute(&self) -> bool322 pub fn get_system_mute(&self) -> bool { 323 self.server_state.get_system_mute() 324 } 325 326 /// Gets a list of output devices 327 /// 328 /// Read a list of the currently attached output devices from the server shared memory. output_devices(&self) -> impl Iterator<Item = CrasIodevInfo>329 pub fn output_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { 330 self.server_state.output_devices() 331 } 332 333 /// Gets a list of input devices 334 /// 335 /// Read a list of the currently attached input devices from the server shared memory. input_devices(&self) -> impl Iterator<Item = CrasIodevInfo>336 pub fn input_devices(&self) -> impl Iterator<Item = CrasIodevInfo> { 337 self.server_state.input_devices() 338 } 339 340 /// Gets a list of output nodes 341 /// 342 /// Read a list of the currently attached output nodes from the server shared memory. output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo>343 pub fn output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { 344 self.server_state.output_nodes() 345 } 346 347 /// Gets a list of input nodes 348 /// 349 /// Read a list of the currently attached input nodes from the server shared memory. input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo>350 pub fn input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> { 351 self.server_state.input_nodes() 352 } 353 354 /// Gets the server's audio debug info. 355 /// 356 /// Sends a message to the server requesting an update of audio debug info, 357 /// waits for the response, and then reads the info from the server state. 358 /// 359 /// # Errors 360 /// 361 /// * If sending the message to the server failed. 362 /// * If an unexpected response message is received. get_audio_debug_info(&mut self) -> Result<AudioDebugInfo>363 pub fn get_audio_debug_info(&mut self) -> Result<AudioDebugInfo> { 364 let header = cras_server_message { 365 length: mem::size_of::<cras_dump_audio_thread>() as u32, 366 id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_DUMP_AUDIO_THREAD, 367 }; 368 let msg = cras_dump_audio_thread { header }; 369 370 self.server_socket.send_server_message_with_fds(&msg, &[])?; 371 372 match CrasClient::wait_for_message(&mut self.server_socket)? { 373 ServerResult::DebugInfoReady => Ok(self 374 .server_state 375 .get_audio_debug_info() 376 .map_err(Error::CrasSysError)?), 377 _ => Err(Error::MessageTypeError), 378 } 379 } 380 381 // Gets next server_stream_id from client and increment stream_id counter. next_server_stream_id(&mut self) -> u32382 fn next_server_stream_id(&mut self) -> u32 { 383 let res = self.next_stream_id; 384 self.next_stream_id += 1; 385 self.server_stream_id(res) 386 } 387 388 // Gets server_stream_id from given stream_id server_stream_id(&self, stream_id: u32) -> u32389 fn server_stream_id(&self, stream_id: u32) -> u32 { 390 (self.client_id << 16) | stream_id 391 } 392 393 // Creates general stream with given parameters create_stream<'b, T: BufferDrop + CrasStreamData<'b>>( &mut self, device_index: Option<u32>, block_size: u32, direction: CRAS_STREAM_DIRECTION, rate: u32, channel_num: usize, format: SampleFormat, ) -> Result<CrasStream<'b, T>>394 fn create_stream<'b, T: BufferDrop + CrasStreamData<'b>>( 395 &mut self, 396 device_index: Option<u32>, 397 block_size: u32, 398 direction: CRAS_STREAM_DIRECTION, 399 rate: u32, 400 channel_num: usize, 401 format: SampleFormat, 402 ) -> Result<CrasStream<'b, T>> { 403 let stream_id = self.next_server_stream_id(); 404 405 // Prepares server message 406 let audio_format = 407 cras_audio_format_packed::new(format.into(), rate, channel_num, direction); 408 let msg_header = cras_server_message { 409 length: mem::size_of::<cras_connect_message>() as u32, 410 id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM, 411 }; 412 let server_cmsg = cras_connect_message { 413 header: msg_header, 414 proto_version: CRAS_PROTO_VER, 415 direction, 416 stream_id, 417 stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT, 418 buffer_frames: block_size, 419 cb_threshold: block_size, 420 flags: 0, 421 format: audio_format, 422 dev_idx: device_index.unwrap_or(CRAS_SPECIAL_DEVICE::NO_DEVICE as u32), 423 effects: 0, 424 client_type: self.client_type, 425 client_shm_size: 0, 426 buffer_offsets: [0, 0], 427 }; 428 429 // Creates AudioSocket pair 430 let (sock1, sock2) = UnixStream::pair()?; 431 432 // Sends `CRAS_SERVER_CONNECT_STREAM` message 433 let socks = [sock2.as_raw_fd()]; 434 self.server_socket 435 .send_server_message_with_fds(&server_cmsg, &socks)?; 436 437 let audio_socket = AudioSocket::new(sock1); 438 loop { 439 let result = CrasClient::wait_for_message(&mut self.server_socket)?; 440 if let ServerResult::StreamConnected(_stream_id, header_fd, samples_fd) = result { 441 return CrasStream::try_new( 442 stream_id, 443 self.server_socket.try_clone()?, 444 block_size, 445 direction, 446 rate, 447 channel_num, 448 format.into(), 449 audio_socket, 450 header_fd, 451 samples_fd, 452 ) 453 .map_err(Error::CrasStreamError); 454 } 455 } 456 } 457 458 /// Creates a new playback stream pinned to the device at `device_index`. 459 /// 460 /// # Arguments 461 /// 462 /// * `device_index` - The device to which the stream will be attached. 463 /// * `num_channels` - The count of audio channels for the stream. 464 /// * `format` - The format to use for stream audio samples. 465 /// * `frame_rate` - The sample rate of the stream. 466 /// * `buffer_size` - The transfer size granularity in frames. 467 #[allow(clippy::type_complexity)] new_pinned_playback_stream( &mut self, device_index: u32, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError>468 pub fn new_pinned_playback_stream( 469 &mut self, 470 device_index: u32, 471 num_channels: usize, 472 format: SampleFormat, 473 frame_rate: u32, 474 buffer_size: usize, 475 ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> 476 { 477 Ok(( 478 Box::new(NoopStreamControl::new()), 479 Box::new(self.create_stream::<CrasPlaybackData>( 480 Some(device_index), 481 buffer_size as u32, 482 CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT, 483 frame_rate, 484 num_channels, 485 format, 486 )?), 487 )) 488 } 489 490 /// Creates a new capture stream pinned to the device at `device_index`. 491 /// 492 /// This is useful for, among other things, capturing from a loopback 493 /// device. 494 /// 495 /// # Arguments 496 /// 497 /// * `device_index` - The device to which the stream will be attached. 498 /// * `num_channels` - The count of audio channels for the stream. 499 /// * `format` - The format to use for stream audio samples. 500 /// * `frame_rate` - The sample rate of the stream. 501 /// * `buffer_size` - The transfer size granularity in frames. 502 #[allow(clippy::type_complexity)] new_pinned_capture_stream( &mut self, device_index: u32, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError>503 pub fn new_pinned_capture_stream( 504 &mut self, 505 device_index: u32, 506 num_channels: usize, 507 format: SampleFormat, 508 frame_rate: u32, 509 buffer_size: usize, 510 ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError> { 511 Ok(( 512 Box::new(NoopStreamControl::new()), 513 Box::new(self.create_stream::<CrasCaptureData>( 514 Some(device_index), 515 buffer_size as u32, 516 CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT, 517 frame_rate, 518 num_channels, 519 format, 520 )?), 521 )) 522 } 523 524 // Blocks handling the first server message received from `socket`. wait_for_message(socket: &mut CrasServerSocket) -> Result<ServerResult>525 fn wait_for_message(socket: &mut CrasServerSocket) -> Result<ServerResult> { 526 #[derive(PollToken)] 527 enum Token { 528 ServerMsg, 529 } 530 let poll_ctx: PollContext<Token> = 531 PollContext::new().and_then(|pc| pc.add(socket, Token::ServerMsg).and(Ok(pc)))?; 532 533 let events = poll_ctx.wait()?; 534 // Check the first readable message 535 let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect(); 536 tokens 537 .get(0) 538 .ok_or(Error::UnexpectedExit) 539 .and_then(|ref token| { 540 match token { 541 Token::ServerMsg => ServerResult::handle_server_message(socket), 542 } 543 .map_err(Into::into) 544 }) 545 } 546 547 /// Returns any open file descriptors needed by CrasClient. 548 /// This function is shared between StreamSource and ShmStreamSource. keep_fds(&self) -> Vec<RawFd>549 fn keep_fds(&self) -> Vec<RawFd> { 550 vec![self.server_socket.as_raw_fd()] 551 } 552 } 553 554 impl<'a> StreamSource for CrasClient<'a> { 555 #[allow(clippy::type_complexity)] new_playback_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError>556 fn new_playback_stream( 557 &mut self, 558 num_channels: usize, 559 format: SampleFormat, 560 frame_rate: u32, 561 buffer_size: usize, 562 ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> 563 { 564 Ok(( 565 Box::new(NoopStreamControl::new()), 566 Box::new(self.create_stream::<CrasPlaybackData>( 567 None, 568 buffer_size as u32, 569 CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT, 570 frame_rate, 571 num_channels, 572 format, 573 )?), 574 )) 575 } 576 577 #[allow(clippy::type_complexity)] new_capture_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError>578 fn new_capture_stream( 579 &mut self, 580 num_channels: usize, 581 format: SampleFormat, 582 frame_rate: u32, 583 buffer_size: usize, 584 ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError> { 585 if self.cras_capture { 586 Ok(( 587 Box::new(NoopStreamControl::new()), 588 Box::new(self.create_stream::<CrasCaptureData>( 589 None, 590 buffer_size as u32, 591 CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT, 592 frame_rate, 593 num_channels, 594 format, 595 )?), 596 )) 597 } else { 598 Ok(( 599 Box::new(NoopStreamControl::new()), 600 Box::new(NoopCaptureStream::new( 601 num_channels, 602 format, 603 frame_rate, 604 buffer_size, 605 )), 606 )) 607 } 608 } 609 keep_fds(&self) -> Option<Vec<RawFd>>610 fn keep_fds(&self) -> Option<Vec<RawFd>> { 611 Some(CrasClient::keep_fds(self)) 612 } 613 } 614 615 impl<'a> ShmStreamSource for CrasClient<'a> { new_stream( &mut self, direction: StreamDirection, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, effects: &[StreamEffect], client_shm: &SharedMemory, buffer_offsets: [u64; 2], ) -> std::result::Result<Box<dyn ShmStream>, BoxError>616 fn new_stream( 617 &mut self, 618 direction: StreamDirection, 619 num_channels: usize, 620 format: SampleFormat, 621 frame_rate: u32, 622 buffer_size: usize, 623 effects: &[StreamEffect], 624 client_shm: &SharedMemory, 625 buffer_offsets: [u64; 2], 626 ) -> std::result::Result<Box<dyn ShmStream>, BoxError> { 627 if direction == StreamDirection::Capture && !self.cras_capture { 628 return Ok(Box::new(NullShmStream::new( 629 buffer_size, 630 num_channels, 631 format, 632 frame_rate, 633 ))); 634 } 635 636 let buffer_size = buffer_size as u32; 637 638 // Prepares server message 639 let stream_id = self.next_server_stream_id(); 640 let audio_format = cras_audio_format_packed::new( 641 format.into(), 642 frame_rate, 643 num_channels, 644 direction.into(), 645 ); 646 let msg_header = cras_server_message { 647 length: mem::size_of::<cras_connect_message>() as u32, 648 id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM, 649 }; 650 651 let server_cmsg = cras_connect_message { 652 header: msg_header, 653 proto_version: CRAS_PROTO_VER, 654 direction: direction.into(), 655 stream_id, 656 stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT, 657 buffer_frames: buffer_size, 658 cb_threshold: buffer_size, 659 flags: 0, 660 format: audio_format, 661 dev_idx: CRAS_SPECIAL_DEVICE::NO_DEVICE as u32, 662 effects: effects.iter().collect::<CrasStreamEffect>().into(), 663 client_type: self.client_type, 664 client_shm_size: client_shm.size(), 665 buffer_offsets, 666 }; 667 668 // Creates AudioSocket pair 669 let (sock1, sock2) = UnixStream::pair()?; 670 671 // Sends `CRAS_SERVER_CONNECT_STREAM` message 672 let fds = [sock2.as_raw_fd(), client_shm.as_raw_fd()]; 673 self.server_socket 674 .send_server_message_with_fds(&server_cmsg, &fds)?; 675 676 loop { 677 let result = CrasClient::wait_for_message(&mut self.server_socket)?; 678 if let ServerResult::StreamConnected(_stream_id, header_fd, _samples_fd) = result { 679 let audio_socket = AudioSocket::new(sock1); 680 let stream = CrasShmStream::try_new( 681 stream_id, 682 self.server_socket.try_clone()?, 683 audio_socket, 684 direction, 685 num_channels, 686 frame_rate, 687 format, 688 header_fd, 689 client_shm.size() as usize, 690 )?; 691 return Ok(Box::new(stream)); 692 } 693 } 694 } 695 keep_fds(&self) -> Vec<RawFd>696 fn keep_fds(&self) -> Vec<RawFd> { 697 CrasClient::keep_fds(self) 698 } 699 } 700