use std::sync::Arc; use std::sync::Mutex; use std::thread::sleep; use std::time::Duration; use anyhow::anyhow; use anyhow::Result; use cpal::traits::StreamTrait; use cpal::traits::{DeviceTrait, HostTrait}; use cpal::Device; use cpal::InputCallbackInfo; use log::debug; use tauri::Window; pub async fn monitor( window: Window, threshold: Arc>, level: Arc>, sens: Arc>, ) { let device = initialize().expect("Unable to init audio"); debug!("Using device {}", device.name().unwrap()); let config = device.default_input_config().unwrap(); let stream = device .build_input_stream( &config.config(), move |data: &[f32], _: &InputCallbackInfo| { if data .iter() .any(|e| (e.abs() * *sens.lock().unwrap()) >= *threshold.lock().unwrap()) { window.emit("mouth-open", "").unwrap(); } else { window.emit("mouth-close", "").unwrap(); } *level.lock().unwrap() = data .iter() .map(|e| e.abs() * *sens.lock().unwrap()) .max_by(|a, b| a.total_cmp(&b)) .unwrap(); }, move |err| { println!("Audio error: {:?}", err); }, ) .unwrap(); stream.play().expect("Error creating input stream"); // The stream will end if it goes out of scope, so just dwell here loop { sleep(Duration::from_secs(5000)); } } fn initialize() -> Result { let host = cpal::default_host(); host.default_input_device() .ok_or_else(|| anyhow!("No default output device")) } #[tauri::command] pub fn get_devices() -> Vec { let host = cpal::default_host(); host.input_devices() .unwrap() .filter_map(|e| e.name().ok()) .collect() }