diff options
Diffstat (limited to 'cras/client/libcras/src/cras_shm_stream.rs')
-rw-r--r-- | cras/client/libcras/src/cras_shm_stream.rs | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/cras/client/libcras/src/cras_shm_stream.rs b/cras/client/libcras/src/cras_shm_stream.rs deleted file mode 100644 index f72cc07c..00000000 --- a/cras/client/libcras/src/cras_shm_stream.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -use std::time::Duration; -use std::{error, fmt}; - -use audio_streams::{ - shm_streams::{BufferSet, ServerRequest, ShmStream}, - BoxError, SampleFormat, StreamDirection, -}; -use cras_sys::gen::CRAS_AUDIO_MESSAGE_ID; -use sys_util::error; - -use crate::audio_socket::{AudioMessage, AudioSocket}; -use crate::cras_server_socket::CrasServerSocket; -use crate::cras_shm::{self, CrasAudioHeader, CrasAudioShmHeaderFd}; - -#[derive(Debug)] -pub enum Error { - MessageTypeError, - CaptureBufferTooSmall, -} - -impl error::Error for Error {} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::MessageTypeError => write!(f, "Message type error"), - Error::CaptureBufferTooSmall => write!( - f, - "Capture buffer too small, must have size at least 'used_size'." - ), - } - } -} - -/// An object that handles interactions with CRAS for a shm stream. -/// The object implements `ShmStream` and so can be used to wait for -/// `ServerRequest` and `BufferComplete` messages. -pub struct CrasShmStream<'a> { - stream_id: u32, - server_socket: CrasServerSocket, - audio_socket: AudioSocket, - direction: StreamDirection, - header: CrasAudioHeader<'a>, - frame_size: usize, - num_channels: usize, - frame_rate: u32, - // The index of the next buffer within SHM to set the buffer offset for. - next_buffer_idx: usize, -} - -impl<'a> CrasShmStream<'a> { - /// Attempt to creates a CrasShmStream with the given arguments. - /// - /// # Arguments - /// - /// * `stream_id` - The server's ID for the stream. - /// * `server_socket` - The socket that is connected to the server. - /// * `audio_socket` - The socket for audio request and audio available messages. - /// * `direction` - The direction of the stream, `Playback` or `Capture`. - /// * `num_channels` - The number of audio channels for the stream. - /// * `format` - The format to use for the stream's samples. - /// * `header_fd` - The file descriptor for the audio header shm area. - /// * `samples_len` - The size of the audio samples shm area. - /// - /// # Returns - /// - /// `CrasShmStream` - CRAS client stream. - /// - /// # Errors - /// - /// * If `header_fd` could not be successfully mmapped. - #[allow(clippy::too_many_arguments)] - pub fn try_new( - stream_id: u32, - server_socket: CrasServerSocket, - audio_socket: AudioSocket, - direction: StreamDirection, - num_channels: usize, - frame_rate: u32, - format: SampleFormat, - header_fd: CrasAudioShmHeaderFd, - samples_len: usize, - ) -> Result<Self, BoxError> { - let header = cras_shm::create_header(header_fd, samples_len)?; - Ok(Self { - stream_id, - server_socket, - audio_socket, - direction, - header, - frame_size: format.sample_bytes() * num_channels, - num_channels, - frame_rate, - // We have either sent zero or two offsets to the server, so we will - // need to update index 0 next. - next_buffer_idx: 0, - }) - } -} - -impl<'a> Drop for CrasShmStream<'a> { - /// Send the disconnect stream message and log an error if sending fails. - fn drop(&mut self) { - if let Err(e) = self.server_socket.disconnect_stream(self.stream_id) { - error!("CrasShmStream::drop error: {}", e); - } - } -} - -impl<'a> ShmStream for CrasShmStream<'a> { - fn frame_size(&self) -> usize { - self.frame_size - } - - fn num_channels(&self) -> usize { - self.num_channels - } - - fn frame_rate(&self) -> u32 { - self.frame_rate - } - - fn wait_for_next_action_with_timeout( - &mut self, - timeout: Duration, - ) -> Result<Option<ServerRequest>, BoxError> { - let expected_id = match self.direction { - StreamDirection::Playback => CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA, - StreamDirection::Capture => CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY, - }; - - match self - .audio_socket - .read_audio_message_with_timeout(Some(timeout))? - { - Some(AudioMessage::Success { id, frames }) if id == expected_id => { - Ok(Some(ServerRequest::new(frames as usize, self))) - } - None => Ok(None), - _ => Err(Box::new(Error::MessageTypeError)), - } - } -} - -impl BufferSet for CrasShmStream<'_> { - fn callback(&mut self, offset: usize, frames: usize) -> Result<(), BoxError> { - self.header - .set_buffer_offset(self.next_buffer_idx, offset)?; - self.next_buffer_idx ^= 1; - let frames = frames as u32; - - match self.direction { - StreamDirection::Playback => { - self.header.commit_written_frames(frames)?; - - // Notify CRAS that we've made playback data available. - self.audio_socket.data_ready(frames)? - } - StreamDirection::Capture => { - let used_size = self.header.get_used_size(); - // Because CRAS doesn't know how long our buffer in shm is, we - // must make sure that there are always at least buffer_size - // frames available so that it doesn't write outside the buffer. - if frames < (used_size / self.frame_size) as u32 { - return Err(Box::new(Error::CaptureBufferTooSmall)); - } - - self.header.commit_read_frames(frames)?; - self.audio_socket.capture_ready(frames)?; - } - } - - Ok(()) - } - - fn ignore(&mut self) -> Result<(), BoxError> { - // We send an empty buffer for an ignored playback request since the - // server will not read from a 0-length buffer. We don't do anything for - // an ignored capture request, since we don't have a way to communicate - // buffer length to the server, and we don't want the server writing - // data to offsets within the SHM area that aren't audio buffers. - if self.direction == StreamDirection::Playback { - self.callback(0, 0)?; - } - - Ok(()) - } -} |