Thread sleep infinite until stop by an event

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?

1 Like

You could use a static variable initialized with once_cell, but you're actually looking for Tauri's State API: see the examples for Manager in tauri - Rust

1 Like

Thanks. I'll check it out.