diff --git a/Cargo.toml b/Cargo.toml index d320529..e7e12e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cpal" -version = "0.2.4" +version = "0.2.5" authors = ["Pierre Krieger "] description = "Cross-platform audio playing library in pure Rust." repository = "https://github.com/tomaka/cpal" diff --git a/src/alsa/mod.rs b/src/alsa/mod.rs index 361a6de..bf79262 100644 --- a/src/alsa/mod.rs +++ b/src/alsa/mod.rs @@ -173,6 +173,7 @@ impl Endpoint { pub struct Voice { channel: Mutex<*mut alsa::snd_pcm_t>, num_channels: u16, + buffer_len: usize, // number of samples that can fit in the buffer } pub struct Buffer<'a, T> { @@ -231,9 +232,18 @@ impl Voice { check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap(); + let buffer_len = { + let obtained_params = HwParams::alloc(); + check_errors(alsa::snd_pcm_hw_params_current(playback_handle, hw_params.0)).unwrap(); + let mut val = mem::uninitialized(); + check_errors(alsa::snd_pcm_hw_params_get_buffer_size(obtained_params.0, &mut val)).unwrap(); + val as usize / format.data_type.get_sample_size() + }; + Ok(Voice { channel: Mutex::new(playback_handle), num_channels: format.channels.len() as u16, + buffer_len: buffer_len, }) } } @@ -264,6 +274,16 @@ impl Voice { unimplemented!() } + pub fn get_pending_samples(&self) -> usize { + let available = { + let channel = self.channel.lock().unwrap(); + let available = unsafe { alsa::snd_pcm_avail(*channel) }; + available * self.num_channels as alsa::snd_pcm_sframes_t + }; + + self.buffer_len - available as usize + } + pub fn underflowed(&self) -> bool { false // TODO: } diff --git a/src/lib.rs b/src/lib.rs index c2d42c5..df40aff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -380,6 +380,16 @@ impl Voice { self.voice.pause() } + /// Returns the number of samples in the buffer that are currently being processed by the + /// audio playback backend. + /// + /// This function is useful to determine how much time it will take to finish playing the + /// current sound. + #[inline] + pub fn get_pending_samples(&self) -> usize { + self.voice.get_pending_samples() + } + /// Returns true if the voice has finished reading all the data you sent to it. #[inline] pub fn underflowed(&self) -> bool { diff --git a/src/null/mod.rs b/src/null/mod.rs index ced23a8..0021a18 100644 --- a/src/null/mod.rs +++ b/src/null/mod.rs @@ -72,6 +72,12 @@ impl Voice { pub fn pause(&mut self) { } + #[inline] + pub fn get_pending_samples(&self) -> usize { + unreachable!() + } + + #[inline] pub fn underflowed(&self) -> bool { false } diff --git a/src/wasapi/voice.rs b/src/wasapi/voice.rs index 789eeec..802d4d2 100644 --- a/src/wasapi/voice.rs +++ b/src/wasapi/voice.rs @@ -193,6 +193,15 @@ impl Voice { } } + pub fn get_pending_samples(&self) -> usize { + unsafe { + let mut padding = mem::uninitialized(); + let hresult = (*self.audio_client).GetCurrentPadding(&mut padding); + check_result(hresult).unwrap(); + padding as usize + } + } + #[inline] pub fn play(&mut self) { if !self.playing {