lasprs 0.14.0

Library for Acoustic Signal Processing (Rust edition, with optional Python bindings via pyo3)
/// Daq apis that are optionally compiled in. Examples:
///
/// - CPAL (Cross-Platform Audio Library)
/// - Loopback (testing API)
use crate::{config::*, siggen::SourceDescriptor};
use crossbeam::channel::*;
use serde::{Deserialize, Serialize};
use std::{any::Any, fmt::Debug, sync::Arc};
use strum::EnumMessage;
use strum_macros;

use super::*;
type Result<T> = std::result::Result<T, StreamMgrError>;

#[cfg(feature = "cpal-api")]
mod api_cpal;
#[cfg(feature = "cpal-api")]
pub use api_cpal::*;

#[cfg(feature = "pulse-api")]
mod api_pulse;

#[cfg(feature = "uldaq-api")]
mod api_uldaq;

#[cfg(feature = "uldaq-api")]
pub use api_uldaq::*;

#[cfg(feature = "loopback-api")]
mod api_loopback;
#[cfg(feature = "loopback-api")]
pub use api_loopback::*;

/// Each API is used to start streams. A stream stops when it is 'dropped'.
pub trait DaqApiMethods: Any + Debug + Send + Sync + 'static {
    /// Obtain device information of devices available for the current API
    fn getDeviceInfo(&self) -> Result<Vec<DeviceInfo>>;

    /// Start an input or duplex stream for a device with a given configuration.
    fn startInputOrDuplexStream(
        &self,
        stype: StreamType,
        devinfo: &DeviceInfo,
        conf: &DaqConfig,
        sender: Sender<InStreamMsg>,
        receiver: Option<Receiver<Arc<RawStreamData>>>,
    ) -> Result<Box<dyn Stream>>;

    /// Start an output-only stream
    fn startOutputStream(
        &self,
        dev: &DeviceInfo,
        cfg: &DaqConfig,
        receiver: Receiver<Arc<RawStreamData>>,
    ) -> Result<Box<dyn Stream>>;

    fn as_any(&self) -> &dyn Any;
}

/// A currently running stream
pub trait Stream: Debug {
    /// Input stream metadata. Only available for input streams
    fn inMetaData(&self) -> Option<Arc<StreamMetaData>>;

    /// Output stream metadata. Only available for output / duplex streams
    fn outMetaData(&self) -> Option<Arc<StreamMetaData>>;

    /// Obtain stream status
    fn status(&self, dir: StreamDirection) -> StreamStatus;
}

/// Stream API descriptor: type and corresponding text
#[cfg_attr(
    feature = "python-bindings",
    gen_stub_pyclass_enum,
    pyclass(eq, eq_int, from_py_object)
)]
#[derive(
    strum_macros::EnumMessage,
    Debug,
    Clone,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    strum_macros::Display,
)]
#[allow(dead_code)]
pub enum DaqApiDescriptor {
    /// CPAL api
    #[strum(message = "Cpal", detailed_message = "Cross-Platform Audio Library")]
    Cpal = 0,
    /// PulseAudio api
    #[strum(message = "Pulse", detailed_message = "Pulseaudio")]
    Pulse = 1,

    /// Loopback (testing) api
    #[strum(message = "Loopback", detailed_message = "Loopback (testing)")]
    Loopback = 2,

    /// Uldaq api
    #[strum(message = "Uldaq", detailed_message = "Uldaq")]
    Uldaq = 3,
}
impl DaqApiDescriptor {
    /// Check whether software is compiled with api `api`. Returns true if so.
    pub fn hasAPI(api: DaqApiDescriptor) -> bool {
        AvailableDaqApis.contains(&api)
    }
    /// Enum message as API name
    pub fn name(&self) -> &'static str {
        self.get_message().unwrap()
    }
}

pub static AvailableDaqApis: &[DaqApiDescriptor] = &[
    #[cfg(feature = "cpal-api")]
    DaqApiDescriptor::Cpal,
    #[cfg(feature = "pulse-api")]
    DaqApiDescriptor::Pulse,
    #[cfg(feature = "loopback-api")]
    DaqApiDescriptor::Loopback,
];

#[cfg(feature = "python-bindings")]
#[cfg_attr(feature = "python-bindings", pymethods)]
impl DaqApiDescriptor {
    fn __str__(&self) -> String {
        self.get_detailed_message().unwrap().to_string()
    }
}