Clippy improvements, some comments added, etc.

This commit is contained in:
Anne de Jong 2024-04-19 12:13:23 +02:00
parent 93c7f71d1c
commit ebdb8a86a1
9 changed files with 80 additions and 42 deletions

View File

@ -96,7 +96,7 @@ impl CpalApi {
let mut oChannelCount = 0; let mut oChannelCount = 0;
let mut avSampleRates = srs_tot.clone(); let mut avSampleRates = srs_tot.clone();
let mut avFramesPerBlock = vec![256 as usize, 512, 1024, 2048, 8192]; let mut avFramesPerBlock = vec![256_usize, 512, 1024, 2048, 8192];
let mut sample_formats = vec![]; let mut sample_formats = vec![];
// Search for sample formats // Search for sample formats
@ -134,7 +134,7 @@ impl CpalApi {
} }
} }
sample_formats.dedup(); sample_formats.dedup();
if sample_formats.len() == 0 { if sample_formats.is_empty() {
continue; continue;
} }
@ -177,7 +177,8 @@ impl CpalApi {
send_ch: Option<Sender<RawStreamData>>, send_ch: Option<Sender<RawStreamData>>,
status: Arc<AtomicCell<StreamStatus>>, status: Arc<AtomicCell<StreamStatus>>,
) -> impl FnMut(cpal::StreamError) { ) -> impl FnMut(cpal::StreamError) {
let errfn = move |err: cpal::StreamError| {
move |err: cpal::StreamError| {
let serr = match err { let serr = match err {
cpal::StreamError::DeviceNotAvailable => StreamError::DeviceNotAvailable, cpal::StreamError::DeviceNotAvailable => StreamError::DeviceNotAvailable,
cpal::StreamError::BackendSpecific { err: _ } => StreamError::DriverError, cpal::StreamError::BackendSpecific { err: _ } => StreamError::DriverError,
@ -186,8 +187,7 @@ impl CpalApi {
sender.send(RawStreamData::StreamError(serr)).unwrap(); sender.send(RawStreamData::StreamError(serr)).unwrap();
} }
status.store(StreamStatus::Error(serr)); status.store(StreamStatus::Error(serr));
}; }
errfn
} }
fn create_incallback<T>( fn create_incallback<T>(
@ -435,14 +435,14 @@ impl CpalApi {
let supported_config = match stype { let supported_config = match stype {
StreamType::Duplex => bail!("Duplex stream not supported for CPAL"), StreamType::Duplex => bail!("Duplex stream not supported for CPAL"),
StreamType::Input => CpalApi::create_cpal_config( StreamType::Input => CpalApi::create_cpal_config(
stype.clone(), stype,
devinfo, devinfo,
conf, conf,
&cpaldev, &cpaldev,
cpaldev.supported_input_configs()?, cpaldev.supported_input_configs()?,
), ),
StreamType::Output => CpalApi::create_cpal_config( StreamType::Output => CpalApi::create_cpal_config(
stype.clone(), stype,
devinfo, devinfo,
conf, conf,
&cpaldev, &cpaldev,
@ -610,7 +610,7 @@ impl CpalApi {
// Create an output stream, using given signal generators for each channel. // Create an output stream, using given signal generators for each channel.
// } // }
pub fn startOutputStream(&self, rx: Receiver<RawStreamData>) -> Result<Box<dyn Stream>> { pub fn startOutputStream(&self, _rx: Receiver<RawStreamData>) -> Result<Box<dyn Stream>> {
bail!("Not implemented"); bail!("Not implemented");
} }
} }

View File

@ -154,7 +154,7 @@ impl DaqConfig {
/// ///
/// * st: string containing TOML data. /// * st: string containing TOML data.
pub fn deserialize_TOML_str(st: &String) -> Result<DaqConfig> { pub fn deserialize_TOML_str(st: &String) -> Result<DaqConfig> {
let res: DaqConfig = toml::from_str(&st)?; let res: DaqConfig = toml::from_str(st)?;
Ok(res) Ok(res)
} }

View File

@ -1,21 +1,21 @@
use super::*; use super::*;
use crate::config::Flt; use crate::config::Flt;
use anyhow::{bail, Error, Result}; use anyhow::{bail, Error, Result};
use clap::builder::OsStr;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use hdf5::types::{VarLenArray, VarLenUnicode}; use hdf5::types::{VarLenArray, VarLenUnicode};
use hdf5::{dataset, datatype, Dataset, File, H5Type}; use hdf5::{dataset, datatype, Dataset, File, H5Type};
use ndarray::ArrayView2; use ndarray::ArrayView2;
use clap::builder::OsStr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::{spawn, JoinHandle}; use std::thread::{spawn, JoinHandle};
use std::time::Duration; use std::time::Duration;
use strum::EnumMessage; use streamdata::*;
use streammgr::*; use streammgr::*;
use streammsg::InStreamMsg; use streammsg::InStreamMsg;
use streamdata::*; use strum::EnumMessage;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Status of a recording /// Status of a recording
@ -51,19 +51,48 @@ pub struct RecordSettings {
/// The delay to wait before adding data /// The delay to wait before adding data
pub startDelay: Duration, pub startDelay: Duration,
} }
impl RecordSettings {
/// Create new record settings. Convenience wrapper to fill in fields in
/// right form. Start delay is optional
///
/// * args:
/// filename: Name of file to record to
/// duration: How long recording should be. Zero means record indefinitely.
/// startDelay: Optional start delay.
pub fn new<T, U>(filename: T, duration: U, startDelay: Option<U>) -> RecordSettings
where
T: Into<PathBuf>,
U: Into<Duration> + Default,
{
RecordSettings {
filename: filename.into(),
duration: duration.into(),
startDelay: startDelay
.map(|s| s.into())
.unwrap_or_else(|| Duration::ZERO),
}
}
}
/// This struct lets a recording run on a stream, waits till the first data arrives and records for a given period of time. Usage: /// This struct lets a recording run on a stream, waits till the first data arrives and records for a given period of time. Usage:
/// ///
/// ``` /// ```
/// use lasprs::{RecordSettings, StreamMgr, Recording}; /// use lasprs::{RecordSettings, StreamMgr, Recording};
/// use std::time::Duration; /// use std::time::Duration;
/// let smgr = StreamMgr::new(); ///
/// fn main() -> anyhow::Result<()> {
/// let mut smgr = StreamMgr::new();
/// smgr.startDefaultInputStream()?; /// smgr.startDefaultInputStream()?;
/// let settings = RecordSettings{ ///
/// filename: "test.h5", /// // Create record settings
/// duration: Duration::from_secs(5), /// let settings = RecordSettings::new(
/// }; /// "test.h5",
/// let rec = Recording::new(settings)?; /// Duration::from_millis(100),
/// None,
/// );
/// let rec = Recording::new(settings, &mut smgr)?;
/// Ok(())
/// }
/// ``` /// ```
pub struct Recording { pub struct Recording {
settings: RecordSettings, settings: RecordSettings,
@ -82,7 +111,7 @@ impl Recording {
where where
T: H5Type, T: H5Type,
{ {
let bs = meta.framesPerBlock as usize; let bs = meta.framesPerBlock;
let nch = meta.nchannels(); let nch = meta.nchannels();
match file match file
.new_dataset::<T>() .new_dataset::<T>()
@ -169,7 +198,7 @@ impl Recording {
pub fn new(mut settings: RecordSettings, mgr: &mut StreamMgr) -> Result<Recording> { pub fn new(mut settings: RecordSettings, mgr: &mut StreamMgr) -> Result<Recording> {
// Append extension if not yet there // Append extension if not yet there
match settings.filename.extension() { match settings.filename.extension() {
Some(a) if a == OsStr::from("h5") => {} Some(a) if a == "h5" => {}
None | Some(_) => { None | Some(_) => {
settings.filename = settings.filename =
(settings.filename.to_string_lossy().to_string() + ".h5").into(); (settings.filename.to_string_lossy().to_string() + ".h5").into();
@ -428,7 +457,7 @@ impl Recording {
impl Drop for Recording { impl Drop for Recording {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(_) = &self.handle { if self.handle.is_some() {
// If we enter here, stop() or cancel() has not been called. In that // If we enter here, stop() or cancel() has not been called. In that
// case, we cleanup here by cancelling the recording // case, we cleanup here by cancelling the recording
self.cancel(); self.cancel();

View File

@ -38,7 +38,7 @@ pub enum RawStreamData {
} }
impl RawStreamData { impl RawStreamData {
pub fn toFloat(&self, nchannels: usize) -> Dmat { pub fn toFloat(&self, _nchannels: usize) -> Dmat {
// match &self { // match &self {
// RawStreamData::Datai8(c) => { // RawStreamData::Datai8(c) => {
// Dmat::zeros((2, 2)); // Dmat::zeros((2, 2));

View File

@ -16,4 +16,4 @@ impl StreamHandler {
smgr.addInQueue(tx); smgr.addInQueue(tx);
StreamHandler{rx} StreamHandler{rx}
} }
} }

View File

@ -5,9 +5,6 @@ use crate::{
config::*, config::*,
siggen::{self, Siggen}, siggen::{self, Siggen},
}; };
use streamcmd::StreamCommand;
use streammsg::*;
use streamdata::*;
use anyhow::{bail, Error, Result}; use anyhow::{bail, Error, Result};
use array_init::from_iter; use array_init::from_iter;
use core::time; use core::time;
@ -18,6 +15,9 @@ use crossbeam::{
}; };
use std::sync::{atomic::AtomicBool, Arc, Mutex}; use std::sync::{atomic::AtomicBool, Arc, Mutex};
use std::thread::{JoinHandle, Thread}; use std::thread::{JoinHandle, Thread};
use streamcmd::StreamCommand;
use streamdata::*;
use streammsg::*;
#[cfg(feature = "cpal-api")] #[cfg(feature = "cpal-api")]
use super::api::api_cpal::CpalApi; use super::api::api_cpal::CpalApi;
@ -90,6 +90,12 @@ impl StreamMgr {
// } // }
// #[pyo3(name = "firstOrderHighPass")] // #[pyo3(name = "firstOrderHighPass")]
} }
impl Default for StreamMgr {
fn default() -> Self {
Self::new()
}
}
impl StreamMgr { impl StreamMgr {
/// Create new stream manager. A stream manager is supposed to be a singleton. /// Create new stream manager. A stream manager is supposed to be a singleton.
/// ///
@ -116,7 +122,7 @@ impl StreamMgr {
smgr.devs = smgr.scanDeviceInfo(); smgr.devs = smgr.scanDeviceInfo();
smgr smgr
} }
/// Get stream status for given stream type. /// Get stream status for given stream type.
pub fn getStatus(&self, t: StreamType) -> StreamStatus { pub fn getStatus(&self, t: StreamType) -> StreamStatus {
match t { match t {
@ -181,7 +187,12 @@ impl StreamMgr {
devinfo devinfo
} }
/// Add a new queue to the lists of queues /// Add a new queue to the lists of queues. On the queue, input data is
/// added.
///
/// If the stream is unable to write data on the queue (which might
/// happen when the handler is dropped), the queue is removed from the list
/// of queues that get data from the stream.
pub fn addInQueue(&mut self, tx: Sender<InStreamMsg>) { pub fn addInQueue(&mut self, tx: Sender<InStreamMsg>) {
if let Some(is) = &self.input_stream { if let Some(is) = &self.input_stream {
is.comm.send(StreamCommand::AddInQueue(tx)).unwrap() is.comm.send(StreamCommand::AddInQueue(tx)).unwrap()
@ -249,14 +260,9 @@ impl StreamMgr {
// Match device info struct on given daq config. // Match device info struct on given daq config.
fn match_devinfo(&self, cfg: &DaqConfig) -> Option<&DeviceInfo> { fn match_devinfo(&self, cfg: &DaqConfig) -> Option<&DeviceInfo> {
for d in self.devs.iter() { self.devs.iter().find(|&d| d.device_name == cfg.device_name)
if d.device_name == cfg.device_name {
return Some(d);
}
}
None
} }
fn startOuputStreamThread<T>( fn startOuputStreamThread(
&mut self, &mut self,
meta: Arc<StreamMetaData>, meta: Arc<StreamMetaData>,
tx: Sender<RawStreamData>, tx: Sender<RawStreamData>,
@ -483,7 +489,7 @@ impl StreamMgr {
let (tx, rx)= unbounded(); let (tx, rx)= unbounded();
let stream = self.cpal_api.startDefaultOutputStream(rx)?; let stream = self.cpal_api.startDefaultOutputStream(rx)?;
let meta = stream.metadata(); let meta = stream.metadata();
let (threadhandle, commtx) = self.startOuputStreamThread::<u16>(meta, tx); let (threadhandle, commtx) = self.startOuputStreamThread(meta, tx);
// Inform all listeners of new stream data // Inform all listeners of new stream data
@ -532,7 +538,9 @@ impl StreamMgr {
comm, comm,
}) = self.output_stream.take() }) = self.output_stream.take()
{ {
if let Err(_) = comm.send(StreamCommand::StopThread){ if comm.send(StreamCommand::StopThread).is_err() {
// Failed to send command over channel. This means the thread is
// already finished due to some other reason.
assert!(threadhandle.is_finished()); assert!(threadhandle.is_finished());
} }
// println!("Wainting for threadhandle to join..."); // println!("Wainting for threadhandle to join...");

View File

@ -168,7 +168,7 @@ impl Filter for Biquad {
self.w2 = 0.; self.w2 = 0.;
} }
fn clone_dyn(&self) -> Box<dyn Filter> { fn clone_dyn(&self) -> Box<dyn Filter> {
Box::new(self.clone()) Box::new(*self)
} }
} }
@ -191,7 +191,7 @@ impl SeriesBiquad {
/// Create new series filter set. See [SeriesBiquad::new()] /// Create new series filter set. See [SeriesBiquad::new()]
/// ///
pub fn new_py<'py>(coefs: PyReadonlyArrayDyn<Flt>) -> PyResult<Self> { pub fn new_py<'py>(coefs: PyReadonlyArrayDyn<Flt>) -> PyResult<Self> {
Ok(SeriesBiquad::new(&coefs.as_slice()?)?) Ok(SeriesBiquad::new(coefs.as_slice()?)?)
} }
#[pyo3(name = "unit")] #[pyo3(name = "unit")]
#[staticmethod] #[staticmethod]

View File

@ -18,6 +18,7 @@ pub mod daq;
pub mod siggen; pub mod siggen;
pub use config::*; pub use config::*;
pub use daq::*;
cfg_if::cfg_if! { cfg_if::cfg_if! {
if #[cfg(feature = "python-bindings")] { if #[cfg(feature = "python-bindings")] {
@ -32,7 +33,7 @@ if #[cfg(feature = "python-bindings")] {
#[pyo3(name="_lasprs")] #[pyo3(name="_lasprs")]
fn lasprs(py: Python, m: &PyModule) -> PyResult<()> { fn lasprs(py: Python, m: &PyModule) -> PyResult<()> {
pyo3_add_submodule_filter(py, &m)?; pyo3_add_submodule_filter(py, m)?;
Ok(()) Ok(())
} }

View File

@ -352,7 +352,7 @@ impl SiggenChannelConfig {
} else { } else {
result.copy_from_slice(source); result.copy_from_slice(source);
if let Some(f) = &mut self.prefilter { if let Some(f) = &mut self.prefilter {
f.filter(&result); f.filter(result);
} }
} }
result.iter_mut().for_each(|x| { result.iter_mut().for_each(|x| {
@ -428,7 +428,7 @@ mod test {
fn test_sample() { fn test_sample() {
assert_eq!(0.5f32.to_sample::<i8>(), 64); assert_eq!(0.5f32.to_sample::<i8>(), 64);
assert_eq!(1.0f32.to_sample::<i8>(), 127); assert_eq!(1.0f32.to_sample::<i8>(), 127);
assert_eq!(-1.0f32.to_sample::<i8>(), -127); assert_eq!(-(1.0f32.to_sample::<i8>()), -127);
assert_eq!(1.0f32.to_sample::<i16>(), i16::MAX); assert_eq!(1.0f32.to_sample::<i16>(), i16::MAX);
} }
} }