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 use std::cmp::min; 5 use std::io; 6 use std::marker::PhantomData; 7 use std::{error, fmt}; 8 9 use audio_streams::{ 10 capture::{CaptureBuffer, CaptureBufferStream}, 11 BoxError, BufferDrop, PlaybackBuffer, PlaybackBufferStream, 12 }; 13 use cras_sys::gen::{snd_pcm_format_t, CRAS_AUDIO_MESSAGE_ID, CRAS_STREAM_DIRECTION}; 14 use sys_util::error; 15 16 use crate::audio_socket::{AudioMessage, AudioSocket}; 17 use crate::cras_server_socket::CrasServerSocket; 18 use crate::cras_shm::*; 19 20 #[derive(Debug)] 21 pub enum Error { 22 IoError(io::Error), 23 MessageTypeError, 24 } 25 26 impl error::Error for Error {} 27 28 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result29 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 30 match self { 31 Error::IoError(ref err) => err.fmt(f), 32 Error::MessageTypeError => write!(f, "Message type error"), 33 } 34 } 35 } 36 37 impl From<io::Error> for Error { from(io_err: io::Error) -> Error38 fn from(io_err: io::Error) -> Error { 39 Error::IoError(io_err) 40 } 41 } 42 43 /// A trait controls the state of `CrasAudioHeader` and 44 /// interacts with server's audio thread through `AudioSocket`. 45 pub trait CrasStreamData<'a>: Send { 46 // Creates `CrasStreamData` with only `AudioSocket`. new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self47 fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self; header_mut(&mut self) -> &mut CrasAudioHeader<'a>48 fn header_mut(&mut self) -> &mut CrasAudioHeader<'a>; audio_sock_mut(&mut self) -> &mut AudioSocket49 fn audio_sock_mut(&mut self) -> &mut AudioSocket; 50 } 51 52 /// `CrasStreamData` implementation for `PlaybackBufferStream`. 53 pub struct CrasPlaybackData<'a> { 54 audio_sock: AudioSocket, 55 header: CrasAudioHeader<'a>, 56 } 57 58 impl<'a> CrasStreamData<'a> for CrasPlaybackData<'a> { new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self59 fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self { 60 Self { audio_sock, header } 61 } 62 header_mut(&mut self) -> &mut CrasAudioHeader<'a>63 fn header_mut(&mut self) -> &mut CrasAudioHeader<'a> { 64 &mut self.header 65 } 66 audio_sock_mut(&mut self) -> &mut AudioSocket67 fn audio_sock_mut(&mut self) -> &mut AudioSocket { 68 &mut self.audio_sock 69 } 70 } 71 72 impl<'a> BufferDrop for CrasPlaybackData<'a> { trigger(&mut self, nframes: usize)73 fn trigger(&mut self, nframes: usize) { 74 let log_err = |e| error!("BufferDrop error: {}", e); 75 if let Err(e) = self.header.commit_written_frames(nframes as u32) { 76 log_err(e); 77 } 78 if let Err(e) = self.audio_sock.data_ready(nframes as u32) { 79 log_err(e); 80 } 81 } 82 } 83 84 /// `CrasStreamData` implementation for `CaptureBufferStream`. 85 pub struct CrasCaptureData<'a> { 86 audio_sock: AudioSocket, 87 header: CrasAudioHeader<'a>, 88 } 89 90 impl<'a> CrasStreamData<'a> for CrasCaptureData<'a> { new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self91 fn new(audio_sock: AudioSocket, header: CrasAudioHeader<'a>) -> Self { 92 Self { audio_sock, header } 93 } 94 header_mut(&mut self) -> &mut CrasAudioHeader<'a>95 fn header_mut(&mut self) -> &mut CrasAudioHeader<'a> { 96 &mut self.header 97 } 98 audio_sock_mut(&mut self) -> &mut AudioSocket99 fn audio_sock_mut(&mut self) -> &mut AudioSocket { 100 &mut self.audio_sock 101 } 102 } 103 104 impl<'a> BufferDrop for CrasCaptureData<'a> { trigger(&mut self, nframes: usize)105 fn trigger(&mut self, nframes: usize) { 106 let log_err = |e| error!("BufferDrop error: {}", e); 107 if let Err(e) = self.header.commit_read_frames(nframes as u32) { 108 log_err(e); 109 } 110 if let Err(e) = self.audio_sock.capture_ready(nframes as u32) { 111 log_err(e); 112 } 113 } 114 } 115 116 #[allow(dead_code)] 117 pub struct CrasStream<'a, T: CrasStreamData<'a> + BufferDrop> { 118 stream_id: u32, 119 server_socket: CrasServerSocket, 120 block_size: u32, 121 direction: CRAS_STREAM_DIRECTION, 122 rate: u32, 123 num_channels: usize, 124 format: snd_pcm_format_t, 125 /// A structure for stream to interact with server audio thread. 126 controls: T, 127 /// The `PhantomData` is used by `controls: T` 128 phantom: PhantomData<CrasAudioHeader<'a>>, 129 audio_buffer: CrasAudioBuffer, 130 } 131 132 impl<'a, T: CrasStreamData<'a> + BufferDrop> CrasStream<'a, T> { 133 /// Creates a CrasStream by given arguments. 134 /// 135 /// # Returns 136 /// `CrasStream` - CRAS client stream. 137 #[allow(clippy::too_many_arguments)] try_new( stream_id: u32, server_socket: CrasServerSocket, block_size: u32, direction: CRAS_STREAM_DIRECTION, rate: u32, num_channels: usize, format: snd_pcm_format_t, audio_sock: AudioSocket, header_fd: CrasAudioShmHeaderFd, samples_fd: CrasShmFd, ) -> Result<Self, Error>138 pub fn try_new( 139 stream_id: u32, 140 server_socket: CrasServerSocket, 141 block_size: u32, 142 direction: CRAS_STREAM_DIRECTION, 143 rate: u32, 144 num_channels: usize, 145 format: snd_pcm_format_t, 146 audio_sock: AudioSocket, 147 header_fd: CrasAudioShmHeaderFd, 148 samples_fd: CrasShmFd, 149 ) -> Result<Self, Error> { 150 let (header, audio_buffer) = create_header_and_buffers(header_fd, samples_fd)?; 151 152 Ok(Self { 153 stream_id, 154 server_socket, 155 block_size, 156 direction, 157 rate, 158 num_channels, 159 format, 160 controls: T::new(audio_sock, header), 161 phantom: PhantomData, 162 audio_buffer, 163 }) 164 } 165 wait_request_data(&mut self) -> Result<(), Error>166 fn wait_request_data(&mut self) -> Result<(), Error> { 167 match self.controls.audio_sock_mut().read_audio_message()? { 168 AudioMessage::Success { 169 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, 170 .. 171 } => Ok(()), 172 _ => Err(Error::MessageTypeError), 173 } 174 } 175 wait_data_ready(&mut self) -> Result<u32, Error>176 fn wait_data_ready(&mut self) -> Result<u32, Error> { 177 match self.controls.audio_sock_mut().read_audio_message()? { 178 AudioMessage::Success { 179 id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, 180 frames, 181 } => Ok(frames), 182 _ => Err(Error::MessageTypeError), 183 } 184 } 185 } 186 187 impl<'a, T: CrasStreamData<'a> + BufferDrop> Drop for CrasStream<'a, T> { 188 /// A blocking drop function, sends the disconnect message to `CrasClient` and waits for 189 /// the return message. 190 /// Logs an error message to stderr if the method fails. drop(&mut self)191 fn drop(&mut self) { 192 if let Err(e) = self.server_socket.disconnect_stream(self.stream_id) { 193 error!("CrasStream::Drop error: {}", e); 194 } 195 } 196 } 197 198 impl<'a, T: CrasStreamData<'a> + BufferDrop> PlaybackBufferStream for CrasStream<'a, T> { next_playback_buffer(&mut self) -> Result<PlaybackBuffer, BoxError>199 fn next_playback_buffer(&mut self) -> Result<PlaybackBuffer, BoxError> { 200 // Wait for request audio message 201 self.wait_request_data()?; 202 let header = self.controls.header_mut(); 203 let frame_size = header.get_frame_size(); 204 let (offset, len) = header.get_write_offset_and_len()?; 205 let buf = &mut self.audio_buffer.get_buffer()[offset..offset + len]; 206 207 PlaybackBuffer::new(frame_size, buf, &mut self.controls).map_err(Box::from) 208 } 209 } 210 211 impl<'a, T: CrasStreamData<'a> + BufferDrop> CaptureBufferStream for CrasStream<'a, T> { next_capture_buffer(&mut self) -> Result<CaptureBuffer, BoxError>212 fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, BoxError> { 213 // Wait for data ready message 214 let frames = self.wait_data_ready()?; 215 let header = self.controls.header_mut(); 216 let frame_size = header.get_frame_size(); 217 let shm_frames = header.get_readable_frames()?; 218 let len = min(shm_frames, frames as usize) * frame_size; 219 let offset = header.get_read_buffer_offset()?; 220 let buf = &mut self.audio_buffer.get_buffer()[offset..offset + len]; 221 222 CaptureBuffer::new(frame_size, buf, &mut self.controls).map_err(Box::from) 223 } 224 } 225