summaryrefslogtreecommitdiff
path: root/cras/client/libcras/src/audio_socket.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cras/client/libcras/src/audio_socket.rs')
-rw-r--r--cras/client/libcras/src/audio_socket.rs316
1 files changed, 0 insertions, 316 deletions
diff --git a/cras/client/libcras/src/audio_socket.rs b/cras/client/libcras/src/audio_socket.rs
deleted file mode 100644
index ac56144c..00000000
--- a/cras/client/libcras/src/audio_socket.rs
+++ /dev/null
@@ -1,316 +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::io;
-use std::io::{Read, Write};
-use std::mem;
-use std::os::unix::{
- io::{AsRawFd, RawFd},
- net::UnixStream,
-};
-use std::time::Duration;
-
-use cras_sys::gen::{audio_message, CRAS_AUDIO_MESSAGE_ID};
-use data_model::DataInit;
-use sys_util::{PollContext, PollToken};
-
-/// A structure for interacting with the CRAS server audio thread through a `UnixStream::pair`.
-pub struct AudioSocket {
- socket: UnixStream,
-}
-
-/// Audio message results which are exchanged by `CrasStream` and CRAS audio server.
-/// through an audio socket.
-#[allow(dead_code)]
-#[derive(Debug)]
-pub enum AudioMessage {
- /// * `id` - Audio message id, which is a `enum CRAS_AUDIO_MESSAGE_ID`.
- /// * `frames` - A `u32` indicating the read or written frame count.
- Success {
- id: CRAS_AUDIO_MESSAGE_ID,
- frames: u32,
- },
- /// * `error` - Error code when a error occurs.
- Error(i32),
-}
-
-/// Converts AudioMessage to raw audio_message for CRAS audio server.
-impl Into<audio_message> for AudioMessage {
- fn into(self) -> audio_message {
- match self {
- AudioMessage::Success { id, frames } => audio_message {
- id,
- error: 0,
- frames,
- },
- AudioMessage::Error(error) => audio_message {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA,
- error,
- frames: 0,
- },
- }
- }
-}
-
-/// Converts AudioMessage from raw audio_message from CRAS audio server.
-impl From<audio_message> for AudioMessage {
- fn from(message: audio_message) -> Self {
- match message.error {
- 0 => AudioMessage::Success {
- id: message.id as CRAS_AUDIO_MESSAGE_ID,
- frames: message.frames,
- },
- error => AudioMessage::Error(error),
- }
- }
-}
-
-impl AudioSocket {
- /// Creates `AudioSocket` from a `UnixStream`.
- ///
- /// # Arguments
- /// `socket` - A `UnixStream`.
- pub fn new(socket: UnixStream) -> Self {
- AudioSocket { socket }
- }
-
- fn read_from_socket<T>(&mut self) -> io::Result<T>
- where
- T: Sized + DataInit + Default,
- {
- let mut message: T = Default::default();
- let rc = self.socket.read(message.as_mut_slice())?;
- if rc == mem::size_of::<T>() {
- Ok(message)
- } else {
- Err(io::Error::new(io::ErrorKind::Other, "Read truncated data."))
- }
- }
-
- /// Blocks reading an `audio message`.
- ///
- /// # Returns
- /// `AudioMessage` - AudioMessage enum.
- ///
- /// # Errors
- /// Returns io::Error if error occurs.
- pub fn read_audio_message(&mut self) -> io::Result<AudioMessage> {
- match self.read_audio_message_with_timeout(None)? {
- None => Err(io::Error::new(io::ErrorKind::Other, "Unexpected exit")),
- Some(message) => Ok(message),
- }
- }
-
- /// Blocks waiting for an `audio message` until `timeout` occurs. If `timeout`
- /// is None, blocks indefinitely.
- ///
- /// # Returns
- /// Some(AudioMessage) - AudioMessage enum if we receive a message before timeout.
- /// None - If the timeout expires.
- ///
- /// # Errors
- /// Returns io::Error if error occurs.
- pub fn read_audio_message_with_timeout(
- &mut self,
- timeout: Option<Duration>,
- ) -> io::Result<Option<AudioMessage>> {
- #[derive(PollToken)]
- enum Token {
- AudioMsg,
- }
- let poll_ctx: PollContext<Token> =
- match PollContext::new().and_then(|pc| pc.add(self, Token::AudioMsg).and(Ok(pc))) {
- Ok(pc) => pc,
- Err(e) => {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- format!("Failed to create PollContext: {}", e),
- ));
- }
- };
- let events = {
- let result = match timeout {
- None => poll_ctx.wait(),
- Some(duration) => poll_ctx.wait_timeout(duration),
- };
- match result {
- Ok(v) => v,
- Err(e) => {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- format!("Failed to poll: {:?}", e),
- ));
- }
- }
- };
-
- // Check the first readable message
- let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect();
- match tokens.get(0) {
- None => Ok(None),
- Some(&Token::AudioMsg) => {
- let raw_msg: audio_message = self.read_from_socket()?;
- Ok(Some(AudioMessage::from(raw_msg)))
- }
- }
- }
-
- /// Sends raw audio message with given AudioMessage enum.
- ///
- /// # Arguments
- /// * `msg` - enum AudioMessage, which could be `Success` with message id
- /// and frames or `Error` with error code.
- ///
- /// # Errors
- /// Returns error if `libc::write` fails.
- fn send_audio_message(&mut self, msg: AudioMessage) -> io::Result<()> {
- let msg: audio_message = msg.into();
- let rc = self.socket.write(msg.as_slice())?;
- if rc < mem::size_of::<audio_message>() {
- Err(io::Error::new(io::ErrorKind::Other, "Sent truncated data."))
- } else {
- Ok(())
- }
- }
-
- /// Sends the data ready message with written frame count.
- ///
- /// # Arguments
- /// * `frames` - An `u32` indicating the written frame count.
- pub fn data_ready(&mut self, frames: u32) -> io::Result<()> {
- self.send_audio_message(AudioMessage::Success {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY,
- frames,
- })
- }
-
- /// Sends the capture ready message with read frame count.
- ///
- /// # Arguments
- ///
- /// * `frames` - An `u32` indicating the number of read frames.
- pub fn capture_ready(&mut self, frames: u32) -> io::Result<()> {
- self.send_audio_message(AudioMessage::Success {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_CAPTURED,
- frames,
- })
- }
-}
-
-impl AsRawFd for AudioSocket {
- fn as_raw_fd(&self) -> RawFd {
- self.socket.as_raw_fd()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- // PartialEq for comparing AudioMessage in tests
- impl PartialEq for AudioMessage {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (
- AudioMessage::Success { id, frames },
- AudioMessage::Success {
- id: other_id,
- frames: other_frames,
- },
- ) => id == other_id && frames == other_frames,
- (AudioMessage::Error(err), AudioMessage::Error(other_err)) => err == other_err,
- _ => false,
- }
- }
- }
-
- fn init_audio_socket_pair() -> (AudioSocket, AudioSocket) {
- let (sock1, sock2) = UnixStream::pair().unwrap();
- let sender = AudioSocket::new(sock1);
- let receiver = AudioSocket::new(sock2);
- (sender, receiver)
- }
-
- #[test]
- fn audio_socket_send_and_recv_audio_message() {
- let (mut sender, mut receiver) = init_audio_socket_pair();
- let message_succ = AudioMessage::Success {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA,
- frames: 0,
- };
- sender.send_audio_message(message_succ).unwrap();
- let res = receiver.read_audio_message().unwrap();
- assert_eq!(
- res,
- AudioMessage::Success {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_REQUEST_DATA,
- frames: 0
- }
- );
-
- let message_err = AudioMessage::Error(123);
- sender.send_audio_message(message_err).unwrap();
- let res = receiver.read_audio_message().unwrap();
- assert_eq!(res, AudioMessage::Error(123));
- }
-
- #[test]
- fn audio_socket_data_ready_send_and_recv() {
- let (sock1, sock2) = UnixStream::pair().unwrap();
- let mut audio_socket_send = AudioSocket::new(sock1);
- let mut audio_socket_recv = AudioSocket::new(sock2);
- audio_socket_send.data_ready(256).unwrap();
-
- // Test receiving by using raw audio_message since CRAS audio server use this.
- let audio_msg: audio_message = audio_socket_recv.read_from_socket().unwrap();
- let ref_audio_msg = audio_message {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_READY,
- error: 0,
- frames: 256,
- };
- // Use brace to copy unaligned data locally
- assert_eq!({ audio_msg.id }, { ref_audio_msg.id });
- assert_eq!({ audio_msg.error }, { ref_audio_msg.error });
- assert_eq!({ audio_msg.frames }, { ref_audio_msg.frames });
- }
-
- #[test]
- fn audio_socket_capture_ready() {
- let (sock1, sock2) = UnixStream::pair().unwrap();
- let mut audio_socket_send = AudioSocket::new(sock1);
- let mut audio_socket_recv = AudioSocket::new(sock2);
- audio_socket_send
- .capture_ready(256)
- .expect("Failed to send capture ready message.");
-
- // Test receiving by using raw audio_message since CRAS audio server use this.
- let audio_msg: audio_message = audio_socket_recv
- .read_from_socket()
- .expect("Failed to read audio message from AudioSocket.");
- let ref_audio_msg = audio_message {
- id: CRAS_AUDIO_MESSAGE_ID::AUDIO_MESSAGE_DATA_CAPTURED,
- error: 0,
- frames: 256,
- };
- // Use brace to copy unaligned data locally
- assert_eq!({ audio_msg.id }, { ref_audio_msg.id });
- assert_eq!({ audio_msg.error }, { ref_audio_msg.error });
- assert_eq!({ audio_msg.frames }, { ref_audio_msg.frames });
- }
-
- #[test]
- fn audio_socket_send_when_broken_pipe() {
- let sock1 = {
- let (sock1, _) = UnixStream::pair().unwrap();
- sock1
- };
- let mut audio_socket = AudioSocket::new(sock1);
- let res = audio_socket.data_ready(256);
- //Broken pipe
- assert_eq!(
- res.expect_err("Result should be an error.").kind(),
- io::Error::from_raw_os_error(32).kind(),
- "Error should be broken pipe.",
- );
- }
-}