Clippy improvements, some comments added, etc.
This commit is contained in:
parent
93c7f71d1c
commit
ebdb8a86a1
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
|
@ -16,4 +16,4 @@ impl StreamHandler {
|
|||||||
smgr.addInQueue(tx);
|
smgr.addInQueue(tx);
|
||||||
StreamHandler{rx}
|
StreamHandler{rx}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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...");
|
||||||
|
@ -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]
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user