use anyhow::Context;
use log::{debug, error};
use wasapi::{AudioClient, Direction, SampleType, StreamMode, WaveFormat};
use crate::common::result::Result;
use crate::common::source::AudioSource;
use crate::common::stream::{CHANNELS, SAMPLE_RATE};
pub const STORE_BITS: usize = 32; pub const VALID_BITS: usize = 32; pub const BLOCKALIGN: usize = CHANNELS * size_of::<f32>(); pub const SAMPLE_TYPE: SampleType = SampleType::Float;
pub struct LinkState {
pub audio_client: AudioClient,
pub capture_client: wasapi::AudioCaptureClient,
pub handle: wasapi::Handle,
pub buffer: Box<[u8]>,
}
impl LinkState {
pub fn link(source: &AudioSource, _frames: usize) -> Result<Self> {
let format = &WaveFormat::new(STORE_BITS, VALID_BITS, &SAMPLE_TYPE, SAMPLE_RATE, CHANNELS, None);
let mut audio_client = AudioClient::new_application_loopback_client(source.id[0], true)?;
let mode = StreamMode::EventsShared {
autoconvert: true,
buffer_duration_hns: 0, };
audio_client.initialize_client(format, &Direction::Capture, &mode)?;
let capture_client = audio_client.get_audiocaptureclient()
.context("Failed to get audio capture client")?;
let handle = audio_client.set_get_eventhandle()
.context("Failed to get audio event handle")?;
let buffer_size = audio_client.get_buffer_size()
.context("Failed to get buffer size")? as usize;
let buffer = vec![0u8; buffer_size * BLOCKALIGN].into_boxed_slice();
audio_client.start_stream()
.context("Failed to start stream")?;
Ok(Self { audio_client, capture_client, handle, buffer })
}
}
impl Drop for LinkState {
fn drop(&mut self) {
if let Err(e) = self.audio_client.stop_stream() {
error!("cleanup failed: {e}");
}
}
}