From d9bfc97b599af4e4e96ae403df8287a533223e32 Mon Sep 17 00:00:00 2001 From: Felix Kaaman Date: Fri, 21 Feb 2020 23:24:55 +0200 Subject: Add seeking to audio player Adds a new "!seek" command which takes in a string that will be parsed by humantime in addition to a '+' or '-' character that can be prefixed to determine if it is a relative seek. Without any prefix characters the seek will be absolute. --- src/audio_player.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src/audio_player.rs') diff --git a/src/audio_player.rs b/src/audio_player.rs index 97ecfbf..9ed645d 100644 --- a/src/audio_player.rs +++ b/src/audio_player.rs @@ -1,4 +1,5 @@ use std::sync::Once; +use std::time::Duration; use gst::prelude::*; use gst::GhostPad; @@ -14,6 +15,13 @@ use tokio02::sync::mpsc::UnboundedSender; static GST_INIT: Once = Once::new(); +#[derive(Copy, Clone, Debug)] +pub enum Seek { + Positive(Duration), + Negative(Duration), + Absolute(Duration), +} + #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum PollResult { Continue, @@ -219,6 +227,41 @@ impl AudioPlayer { Ok(()) } + pub fn seek(&self, seek: Seek) -> Result { + let base = match seek { + Seek::Positive(_) | Seek::Negative(_) => { + let pos = self + .pipeline + .query_position::() + .ok_or(AudioPlayerError::SeekError)?; + Duration::from_nanos(pos.nanoseconds().ok_or(AudioPlayerError::SeekError)?) + } + _ => Duration::new(0, 0), + }; + + let absolute = match seek { + Seek::Positive(duration) => base + duration, + Seek::Negative(duration) => { + if duration > base { + Duration::new(0, 0) + } else { + base - duration + } + } + Seek::Absolute(duration) => duration, + }; + + let time = humantime::format_duration(absolute); + info!("Seeking to {}", time); + + self.pipeline.seek_simple( + gst::SeekFlags::FLUSH, + gst::ClockTime::from_nseconds(absolute.as_nanos() as _), + )?; + + Ok(time) + } + pub fn stop_current(&self) -> Result<(), AudioPlayerError> { info!("Stopping pipeline, sending EOS"); @@ -334,6 +377,7 @@ impl AudioPlayer { pub enum AudioPlayerError { GStreamerError(glib::error::BoolError), StateChangeFailed, + SeekError, } impl From for AudioPlayerError { -- cgit v1.2.3-70-g09d2