Hello,
I've been trying to solve this the whole weekend but no luck so far. I'm developing a DAW-like software with Tauri. Basically, I want to record an audio until I press a stop button.
pub async fn record_instrument(audio_id: String, user_id: i32) {
info!("Start recording: audio_id:{} user_id:{}", audio_id, user_id);
// Find devices.
let input_device = if let Ok(device) = get_soundcard(AudioDevice::Input) {
device
} else {
info!("Failed to get soundcard input.");
return;
};
let input_config = match input_device.default_input_config() {
Ok(c) => c,
Err(e) => {
error!("failed to find input config: {}", e);
return;
}
};
// The WAV file we're recording to.
let recording_path = match get_recording_path(audio_id, user_id.to_string(), Mode::Bass).await {
Ok(path) => path,
Err(e) => {
error!("failed to get audio directory: {}", e);
return;
}
};
debug!("Recording path: {}", recording_path);
let spec = wav_spec_from_config(&input_config);
let writer = match WavWriter::create(&recording_path, spec) {
Ok(w) => w,
Err(e) => {
error!("Failed to create wav writer: {}", e);
return;
}
};
let writer = Arc::new(Mutex::new(Some(writer)));
// Run the input stream on a separate thread.
let input_stream_writer = writer.clone();
let err_fn = move |err| {
error!("an error occurred on stream: {}", err);
};
let stream = match input_config.sample_format() {
SampleFormat::I8 => input_device.build_input_stream(
&input_config.into(),
move |data, _: &_| write_input_data::<i8, i8>(data, &input_stream_writer),
err_fn,
None,
),
SampleFormat::I16 => input_device.build_input_stream(
&input_config.into(),
move |data, _: &_| write_input_data::<i16, i16>(data, &input_stream_writer),
err_fn,
None,
),
SampleFormat::I32 => input_device.build_input_stream(
&input_config.into(),
move |data, _: &_| write_input_data::<i32, i32>(data, &input_stream_writer),
err_fn,
None,
),
SampleFormat::F32 => input_device.build_input_stream(
&input_config.into(),
move |data, _: &_| write_input_data::<f32, f32>(data, &input_stream_writer),
err_fn,
None,
),
_ => {
error!("unsupported sample format");
return;
}
};
let stream = match stream {
Ok(s) => s,
Err(e) => {
error!("failed to build input stream: {}", e);
return;
}
};
let _ = stream.play();
std::thread::sleep(std::time::Duration::from_secs(60));
// Stop recording
if let Ok(mut guard) = writer.try_lock() {
if let Some(writer) = guard.take() {
writer.finalize().ok();
}
}
drop(stream);
info!("Recording {} complete!", recording_path);
}
This is probably related: multithreading - How do I perform interruptible sleep in Rust? - Stack Overflow
I just don't know how to persist the writer and then call the finalize from another Tauri command. Any pointers?