// 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.
//! Provides an interface for playing and recording audio through CRAS server.
//!
//! `CrasClient` implements `StreamSource` trait and it can create playback or capture
//! stream - `CrasStream` which can be a
//! - `PlaybackBufferStream` for audio playback or
//! - `CaptureBufferStream` for audio capture.
//!
//! # Example of file audio playback
//!
//! `PlaybackBuffer`s to be filled with audio samples are obtained by calling
//! `next_playback_buffer` from `CrasStream`.
//!
//! Users playing audio fill the provided buffers with audio. When a `PlaybackBuffer` is dropped,
//! the samples written to it are committed to the `CrasStream` it came from.
//!
//!
//! ```
//! // An example of playing raw audio data from a given file
//! use std::env;
//! use std::fs::File;
//! use std::io::{Read, Write};
//! use std::thread::{spawn, JoinHandle};
//! type Result<T> = std::result::Result<T, BoxError>;
//!
//! use libcras::{BoxError, CrasClient, CrasClientType};
//! use audio_streams::{SampleFormat, StreamSource};
//!
//! const BUFFER_SIZE: usize = 256;
//! const FRAME_RATE: u32 = 44100;
//! const NUM_CHANNELS: usize = 2;
//! const FORMAT: SampleFormat = SampleFormat::S16LE;
//!
//! # fn main() -> Result<()> {
//! #    let args: Vec<String> = env::args().collect();
//! #    match args.len() {
//! #        2 => {
//!              let mut cras_client = CrasClient::new()?;
//!              cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST);
//!              let (_control, mut stream) = cras_client
//!                  .new_playback_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?;
//!
//!              // Plays 1000 * BUFFER_SIZE samples from the given file
//!              let mut file = File::open(&args[1])?;
//!              let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2];
//!              for _i in 0..1000 {
//!                  // Reads data to local buffer
//!                  let _read_count = file.read(&mut local_buffer)?;
//!
//!                  // Gets writable buffer from stream and
//!                  let mut buffer = stream.next_playback_buffer()?;
//!                  // Writes data to stream buffer
//!                  let _write_frames = buffer.write(&local_buffer)?;
//!              }
//!              // Stream and client should gracefully be closed out of this scope
//! #        }
//! #        _ => {
//! #            println!("{} /path/to/playback_file.raw", args[0]);
//! #        }
//! #    };
//! #    Ok(())
//! # }
//! ```
//!
//! # Example of file audio capture
//!
//! `CaptureBuffer`s which contain audio samples are obtained by calling
//! `next_capture_buffer` from `CrasStream`.
//!
//! Users get captured audio samples from the provided buffers. When a `CaptureBuffer` is dropped,
//! the number of read samples will be committed to the `CrasStream` it came from.
//! ```
//! use std::env;
//! use std::fs::File;
//! use std::io::{Read, Write};
//! use std::thread::{spawn, JoinHandle};
//! type Result<T> = std::result::Result<T, BoxError>;
//!
//! use libcras::{BoxError, CrasClient, CrasClientType};
//! use audio_streams::{SampleFormat, StreamSource};
//!
//! const BUFFER_SIZE: usize = 256;
//! const FRAME_RATE: u32 = 44100;
//! const NUM_CHANNELS: usize = 2;
//! const FORMAT: SampleFormat = SampleFormat::S16LE;
//!
//! # fn main() -> Result<()> {
//! #    let args: Vec<String> = env::args().collect();
//! #    match args.len() {
//! #        2 => {
//!              let mut cras_client = CrasClient::new()?;
//!              cras_client.set_client_type(CrasClientType::CRAS_CLIENT_TYPE_TEST);
//!              let (_control, mut stream) = cras_client
//!                  .new_capture_stream(NUM_CHANNELS, FORMAT, FRAME_RATE, BUFFER_SIZE)?;
//!
//!              // Capture 1000 * BUFFER_SIZE samples to the given file
//!              let mut file = File::create(&args[1])?;
//!              let mut local_buffer = [0u8; BUFFER_SIZE * NUM_CHANNELS * 2];
//!              for _i in 0..1000 {
//!
//!                  // Gets readable buffer from stream and
//!                  let mut buffer = stream.next_capture_buffer()?;
//!                  // Reads data to local buffer
//!                  let read_count = buffer.read(&mut local_buffer)?;
//!                  // Writes data to file
//!                  let _read_frames = file.write(&local_buffer[..read_count])?;
//!              }
//!              // Stream and client should gracefully be closed out of this scope
//! #        }
//! #        _ => {
//! #            println!("{} /path/to/capture_file.raw", args[0]);
//! #        }
//! #    };
//! #    Ok(())
//! # }
//! ```
use std::io;
use std::mem;
use std::os::unix::{
    io::{AsRawFd, RawFd},
    net::UnixStream,
};
use std::{error, fmt};

pub use audio_streams::BoxError;
use audio_streams::{
    capture::{CaptureBufferStream, NoopCaptureStream},
    shm_streams::{NullShmStream, ShmStream, ShmStreamSource},
    BufferDrop, NoopStreamControl, PlaybackBufferStream, SampleFormat, StreamControl,
    StreamDirection, StreamEffect, StreamSource,
};
use cras_sys::gen::*;
pub use cras_sys::gen::{
    CRAS_CLIENT_TYPE as CrasClientType, CRAS_NODE_TYPE as CrasNodeType,
    CRAS_STREAM_EFFECT as CrasStreamEffect,
};
pub use cras_sys::{AudioDebugInfo, CrasIodevInfo, CrasIonodeInfo};
use sys_util::{PollContext, PollToken, SharedMemory};

mod audio_socket;
use crate::audio_socket::AudioSocket;
mod cras_server_socket;
use crate::cras_server_socket::CrasServerSocket;
pub use crate::cras_server_socket::CrasSocketType;
mod cras_shm;
use crate::cras_shm::CrasServerState;
pub mod cras_shm_stream;
use crate::cras_shm_stream::CrasShmStream;
mod cras_stream;
use crate::cras_stream::{CrasCaptureData, CrasPlaybackData, CrasStream, CrasStreamData};
mod cras_client_message;
use crate::cras_client_message::*;

#[derive(Debug)]
pub enum Error {
    CrasClientMessageError(cras_client_message::Error),
    CrasStreamError(cras_stream::Error),
    CrasSysError(cras_sys::Error),
    IoError(io::Error),
    SysUtilError(sys_util::Error),
    MessageTypeError,
    UnexpectedExit,
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::CrasClientMessageError(ref err) => err.fmt(f),
            Error::CrasStreamError(ref err) => err.fmt(f),
            Error::CrasSysError(ref err) => err.fmt(f),
            Error::IoError(ref err) => err.fmt(f),
            Error::SysUtilError(ref err) => err.fmt(f),
            Error::MessageTypeError => write!(f, "Message type error"),
            Error::UnexpectedExit => write!(f, "Unexpected exit"),
        }
    }
}

type Result<T> = std::result::Result<T, Error>;

impl From<io::Error> for Error {
    fn from(io_err: io::Error) -> Self {
        Error::IoError(io_err)
    }
}

impl From<sys_util::Error> for Error {
    fn from(sys_util_err: sys_util::Error) -> Self {
        Error::SysUtilError(sys_util_err)
    }
}

impl From<cras_stream::Error> for Error {
    fn from(err: cras_stream::Error) -> Self {
        Error::CrasStreamError(err)
    }
}

impl From<cras_client_message::Error> for Error {
    fn from(err: cras_client_message::Error) -> Self {
        Error::CrasClientMessageError(err)
    }
}

/// A CRAS server client, which implements StreamSource and ShmStreamSource.
/// It can create audio streams connecting to CRAS server.
pub struct CrasClient<'a> {
    server_socket: CrasServerSocket,
    server_state: CrasServerState<'a>,
    client_id: u32,
    next_stream_id: u32,
    cras_capture: bool,
    client_type: CRAS_CLIENT_TYPE,
}

impl<'a> CrasClient<'a> {
    /// Blocks creating a `CrasClient` with registered `client_id`
    ///
    /// # Results
    ///
    /// * `CrasClient` - A client to interact with CRAS server
    ///
    /// # Errors
    ///
    /// Returns error if error occurs while handling server message or message
    /// type is incorrect
    pub fn new() -> Result<Self> {
        Self::with_type(CrasSocketType::Legacy)
    }

    /// Tries to create a `CrasClient` with a given `CrasSocketType`.
    ///
    /// # Errors
    ///
    /// Returns error if error occurs while handling server message or message
    /// type is incorrect.
    pub fn with_type(socket_type: CrasSocketType) -> Result<Self> {
        // Create a connection to the server.
        let mut server_socket = CrasServerSocket::with_type(socket_type)?;
        // Gets client ID and server state fd from server
        if let ServerResult::Connected(client_id, server_state_fd) =
            CrasClient::wait_for_message(&mut server_socket)?
        {
            Ok(Self {
                server_socket,
                server_state: CrasServerState::try_new(server_state_fd)?,
                client_id,
                next_stream_id: 0,
                cras_capture: false,
                client_type: CRAS_CLIENT_TYPE::CRAS_CLIENT_TYPE_UNKNOWN,
            })
        } else {
            Err(Error::MessageTypeError)
        }
    }

    /// Enables capturing audio through CRAS server.
    pub fn enable_cras_capture(&mut self) {
        self.cras_capture = true;
    }

    /// Set the type of this client to report to CRAS when connecting streams.
    pub fn set_client_type(&mut self, client_type: CRAS_CLIENT_TYPE) {
        self.client_type = client_type;
    }

    /// Sets the system volume to `volume`.
    ///
    /// Send a message to the server to request setting the system volume
    /// to `volume`. No response is returned from the server.
    ///
    /// # Errors
    ///
    /// If writing the message to the server socket failed.
    pub fn set_system_volume(&mut self, volume: u32) -> Result<()> {
        let header = cras_server_message {
            length: mem::size_of::<cras_set_system_volume>() as u32,
            id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_VOLUME,
        };
        let msg = cras_set_system_volume { header, volume };

        self.server_socket.send_server_message_with_fds(&msg, &[])?;
        Ok(())
    }

    /// Sets the system mute status to `mute`.
    ///
    /// Send a message to the server to request setting the system mute
    /// to `mute`. No response is returned from the server.
    ///
    /// # Errors
    ///
    /// If writing the message to the server socket failed.
    pub fn set_system_mute(&mut self, mute: bool) -> Result<()> {
        let header = cras_server_message {
            length: mem::size_of::<cras_set_system_mute>() as u32,
            id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_SET_SYSTEM_MUTE,
        };
        let msg = cras_set_system_mute {
            header,
            mute: mute as i32,
        };

        self.server_socket.send_server_message_with_fds(&msg, &[])?;
        Ok(())
    }

    /// Gets the system volume.
    ///
    /// Read the current value for system volume from the server shared memory.
    pub fn get_system_volume(&self) -> u32 {
        self.server_state.get_system_volume()
    }

    /// Gets the system mute.
    ///
    /// Read the current value for system mute from the server shared memory.
    pub fn get_system_mute(&self) -> bool {
        self.server_state.get_system_mute()
    }

    /// Gets a list of output devices
    ///
    /// Read a list of the currently attached output devices from the server shared memory.
    pub fn output_devices(&self) -> impl Iterator<Item = CrasIodevInfo> {
        self.server_state.output_devices()
    }

    /// Gets a list of input devices
    ///
    /// Read a list of the currently attached input devices from the server shared memory.
    pub fn input_devices(&self) -> impl Iterator<Item = CrasIodevInfo> {
        self.server_state.input_devices()
    }

    /// Gets a list of output nodes
    ///
    /// Read a list of the currently attached output nodes from the server shared memory.
    pub fn output_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> {
        self.server_state.output_nodes()
    }

    /// Gets a list of input nodes
    ///
    /// Read a list of the currently attached input nodes from the server shared memory.
    pub fn input_nodes(&self) -> impl Iterator<Item = CrasIonodeInfo> {
        self.server_state.input_nodes()
    }

    /// Gets the server's audio debug info.
    ///
    /// Sends a message to the server requesting an update of audio debug info,
    /// waits for the response, and then reads the info from the server state.
    ///
    /// # Errors
    ///
    /// * If sending the message to the server failed.
    /// * If an unexpected response message is received.
    pub fn get_audio_debug_info(&mut self) -> Result<AudioDebugInfo> {
        let header = cras_server_message {
            length: mem::size_of::<cras_dump_audio_thread>() as u32,
            id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_DUMP_AUDIO_THREAD,
        };
        let msg = cras_dump_audio_thread { header };

        self.server_socket.send_server_message_with_fds(&msg, &[])?;

        match CrasClient::wait_for_message(&mut self.server_socket)? {
            ServerResult::DebugInfoReady => Ok(self
                .server_state
                .get_audio_debug_info()
                .map_err(Error::CrasSysError)?),
            _ => Err(Error::MessageTypeError),
        }
    }

    // Gets next server_stream_id from client and increment stream_id counter.
    fn next_server_stream_id(&mut self) -> u32 {
        let res = self.next_stream_id;
        self.next_stream_id += 1;
        self.server_stream_id(res)
    }

    // Gets server_stream_id from given stream_id
    fn server_stream_id(&self, stream_id: u32) -> u32 {
        (self.client_id << 16) | stream_id
    }

    // Creates general stream with given parameters
    fn 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>> {
        let stream_id = self.next_server_stream_id();

        // Prepares server message
        let audio_format =
            cras_audio_format_packed::new(format.into(), rate, channel_num, direction);
        let msg_header = cras_server_message {
            length: mem::size_of::<cras_connect_message>() as u32,
            id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM,
        };
        let server_cmsg = cras_connect_message {
            header: msg_header,
            proto_version: CRAS_PROTO_VER,
            direction,
            stream_id,
            stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT,
            buffer_frames: block_size,
            cb_threshold: block_size,
            flags: 0,
            format: audio_format,
            dev_idx: device_index.unwrap_or(CRAS_SPECIAL_DEVICE::NO_DEVICE as u32),
            effects: 0,
            client_type: self.client_type,
            client_shm_size: 0,
            buffer_offsets: [0, 0],
        };

        // Creates AudioSocket pair
        let (sock1, sock2) = UnixStream::pair()?;

        // Sends `CRAS_SERVER_CONNECT_STREAM` message
        let socks = [sock2.as_raw_fd()];
        self.server_socket
            .send_server_message_with_fds(&server_cmsg, &socks)?;

        let audio_socket = AudioSocket::new(sock1);
        loop {
            let result = CrasClient::wait_for_message(&mut self.server_socket)?;
            if let ServerResult::StreamConnected(_stream_id, header_fd, samples_fd) = result {
                return CrasStream::try_new(
                    stream_id,
                    self.server_socket.try_clone()?,
                    block_size,
                    direction,
                    rate,
                    channel_num,
                    format.into(),
                    audio_socket,
                    header_fd,
                    samples_fd,
                )
                .map_err(Error::CrasStreamError);
            }
        }
    }

    /// Creates a new playback stream pinned to the device at `device_index`.
    ///
    /// # Arguments
    ///
    /// * `device_index` - The device to which the stream will be attached.
    /// * `num_channels` - The count of audio channels for the stream.
    /// * `format` - The format to use for stream audio samples.
    /// * `frame_rate` - The sample rate of the stream.
    /// * `buffer_size` - The transfer size granularity in frames.
    #[allow(clippy::type_complexity)]
    pub fn 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>
    {
        Ok((
            Box::new(NoopStreamControl::new()),
            Box::new(self.create_stream::<CrasPlaybackData>(
                Some(device_index),
                buffer_size as u32,
                CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT,
                frame_rate,
                num_channels,
                format,
            )?),
        ))
    }

    /// Creates a new capture stream pinned to the device at `device_index`.
    ///
    /// This is useful for, among other things, capturing from a loopback
    /// device.
    ///
    /// # Arguments
    ///
    /// * `device_index` - The device to which the stream will be attached.
    /// * `num_channels` - The count of audio channels for the stream.
    /// * `format` - The format to use for stream audio samples.
    /// * `frame_rate` - The sample rate of the stream.
    /// * `buffer_size` - The transfer size granularity in frames.
    #[allow(clippy::type_complexity)]
    pub fn 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> {
        Ok((
            Box::new(NoopStreamControl::new()),
            Box::new(self.create_stream::<CrasCaptureData>(
                Some(device_index),
                buffer_size as u32,
                CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT,
                frame_rate,
                num_channels,
                format,
            )?),
        ))
    }

    // Blocks handling the first server message received from `socket`.
    fn wait_for_message(socket: &mut CrasServerSocket) -> Result<ServerResult> {
        #[derive(PollToken)]
        enum Token {
            ServerMsg,
        }
        let poll_ctx: PollContext<Token> =
            PollContext::new().and_then(|pc| pc.add(socket, Token::ServerMsg).and(Ok(pc)))?;

        let events = poll_ctx.wait()?;
        // Check the first readable message
        let tokens: Vec<Token> = events.iter_readable().map(|e| e.token()).collect();
        tokens
            .get(0)
            .ok_or(Error::UnexpectedExit)
            .and_then(|ref token| {
                match token {
                    Token::ServerMsg => ServerResult::handle_server_message(socket),
                }
                .map_err(Into::into)
            })
    }

    /// Returns any open file descriptors needed by CrasClient.
    /// This function is shared between StreamSource and ShmStreamSource.
    fn keep_fds(&self) -> Vec<RawFd> {
        vec![self.server_socket.as_raw_fd()]
    }
}

impl<'a> StreamSource for CrasClient<'a> {
    #[allow(clippy::type_complexity)]
    fn 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>
    {
        Ok((
            Box::new(NoopStreamControl::new()),
            Box::new(self.create_stream::<CrasPlaybackData>(
                None,
                buffer_size as u32,
                CRAS_STREAM_DIRECTION::CRAS_STREAM_OUTPUT,
                frame_rate,
                num_channels,
                format,
            )?),
        ))
    }

    #[allow(clippy::type_complexity)]
    fn 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> {
        if self.cras_capture {
            Ok((
                Box::new(NoopStreamControl::new()),
                Box::new(self.create_stream::<CrasCaptureData>(
                    None,
                    buffer_size as u32,
                    CRAS_STREAM_DIRECTION::CRAS_STREAM_INPUT,
                    frame_rate,
                    num_channels,
                    format,
                )?),
            ))
        } else {
            Ok((
                Box::new(NoopStreamControl::new()),
                Box::new(NoopCaptureStream::new(
                    num_channels,
                    format,
                    frame_rate,
                    buffer_size,
                )),
            ))
        }
    }

    fn keep_fds(&self) -> Option<Vec<RawFd>> {
        Some(CrasClient::keep_fds(self))
    }
}

impl<'a> ShmStreamSource for CrasClient<'a> {
    fn 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> {
        if direction == StreamDirection::Capture && !self.cras_capture {
            return Ok(Box::new(NullShmStream::new(
                buffer_size,
                num_channels,
                format,
                frame_rate,
            )));
        }

        let buffer_size = buffer_size as u32;

        // Prepares server message
        let stream_id = self.next_server_stream_id();
        let audio_format = cras_audio_format_packed::new(
            format.into(),
            frame_rate,
            num_channels,
            direction.into(),
        );
        let msg_header = cras_server_message {
            length: mem::size_of::<cras_connect_message>() as u32,
            id: CRAS_SERVER_MESSAGE_ID::CRAS_SERVER_CONNECT_STREAM,
        };

        let server_cmsg = cras_connect_message {
            header: msg_header,
            proto_version: CRAS_PROTO_VER,
            direction: direction.into(),
            stream_id,
            stream_type: CRAS_STREAM_TYPE::CRAS_STREAM_TYPE_DEFAULT,
            buffer_frames: buffer_size,
            cb_threshold: buffer_size,
            flags: 0,
            format: audio_format,
            dev_idx: CRAS_SPECIAL_DEVICE::NO_DEVICE as u32,
            effects: effects.iter().collect::<CrasStreamEffect>().into(),
            client_type: self.client_type,
            client_shm_size: client_shm.size(),
            buffer_offsets,
        };

        // Creates AudioSocket pair
        let (sock1, sock2) = UnixStream::pair()?;

        // Sends `CRAS_SERVER_CONNECT_STREAM` message
        let fds = [sock2.as_raw_fd(), client_shm.as_raw_fd()];
        self.server_socket
            .send_server_message_with_fds(&server_cmsg, &fds)?;

        loop {
            let result = CrasClient::wait_for_message(&mut self.server_socket)?;
            if let ServerResult::StreamConnected(_stream_id, header_fd, _samples_fd) = result {
                let audio_socket = AudioSocket::new(sock1);
                let stream = CrasShmStream::try_new(
                    stream_id,
                    self.server_socket.try_clone()?,
                    audio_socket,
                    direction,
                    num_channels,
                    frame_rate,
                    format,
                    header_fd,
                    client_shm.size() as usize,
                )?;
                return Ok(Box::new(stream));
            }
        }
    }

    fn keep_fds(&self) -> Vec<RawFd> {
        CrasClient::keep_fds(self)
    }
}
