71 lines
1.9 KiB
Rust
71 lines
1.9 KiB
Rust
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<Mutex<f32>>,
|
|
level: Arc<Mutex<f32>>,
|
|
sens: Arc<Mutex<f32>>,
|
|
) {
|
|
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<Device> {
|
|
let host = cpal::default_host();
|
|
host.default_input_device()
|
|
.ok_or_else(|| anyhow!("No default output device"))
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn get_devices() -> Vec<String> {
|
|
let host = cpal::default_host();
|
|
host.input_devices()
|
|
.unwrap()
|
|
.filter_map(|e| e.name().ok())
|
|
.collect()
|
|
}
|