From 76de72cdca2442cec026ed5664a5364a03c833f6 Mon Sep 17 00:00:00 2001 From: jazzfool Date: Sun, 23 Aug 2020 19:03:29 +1000 Subject: [PATCH] minor enhancements --- examples/minimal.rs | 20 ++++++++++-- src/lib.rs | 77 +++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 30 deletions(-) diff --git a/examples/minimal.rs b/examples/minimal.rs index 90bb42d..987f425 100644 --- a/examples/minimal.rs +++ b/examples/minimal.rs @@ -1,4 +1,6 @@ -use iced::{button, executor, Application, Button, Column, Command, Element, Subscription, Text}; +use iced::{ + button, executor, Application, Button, Column, Command, Element, Row, Subscription, Text, +}; use iced_video_player::{VideoPlayer, VideoPlayerMessage}; fn main() { @@ -65,8 +67,20 @@ impl Application for App { Column::new() .push(self.video.frame_view()) .push( - Button::new(&mut self.pause_btn, Text::new("Toggle Pause")) - .on_press(Message::TogglePause), + Row::new() + .spacing(5) + .push( + Button::new( + &mut self.pause_btn, + Text::new(if self.video.paused() { "Play" } else { "Pause" }), + ) + .on_press(Message::TogglePause), + ) + .push(Text::new(format!( + "{:#?}s / {:#?}s", + self.video.position().unwrap().as_secs(), + self.video.duration().as_secs() + ))), ) .into() } diff --git a/src/lib.rs b/src/lib.rs index 4d644f4..f041997 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,37 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use thiserror::Error; +/// Position in the media. +pub enum Position { + /// Position based on time. + /// + /// Not the most accurate format for videos. + Time(std::time::Duration), + /// Position based on nth frame. + Frame(u64), +} + +impl From for gst::GenericFormattedValue { + fn from(pos: Position) -> Self { + match pos { + Position::Time(t) => gst::ClockTime::from_nseconds(t.as_nanos() as _).into(), + Position::Frame(f) => gst::format::Default(Some(f)).into(), + } + } +} + +impl From for Position { + fn from(t: std::time::Duration) -> Self { + Position::Time(t) + } +} + +impl From for Position { + fn from(f: u64) -> Self { + Position::Frame(f) + } +} + #[derive(Debug, Error)] pub enum Error { #[error("{0}")] @@ -45,7 +76,8 @@ pub struct VideoPlayer { duration: std::time::Duration, frame: Arc>>, - pause: bool, + paused: bool, + muted: bool, } impl Drop for VideoPlayer { @@ -118,8 +150,8 @@ impl VideoPlayer { source.set_state(gst::State::Playing)?; - // wait for up to 1 second until the decoder gets the source capabilities - source.get_state(gst::ClockTime::from_seconds(1)).0?; + // wait for up to 5 seconds until the decoder gets the source capabilities + source.get_state(gst::ClockTime::from_seconds(5)).0?; // extract resolution and framerate // TODO(jazzfool): maybe we want to extract some other information too? @@ -160,7 +192,8 @@ impl VideoPlayer { duration, frame, - pause: false, + paused: false, + muted: false, }) } @@ -183,24 +216,19 @@ impl VideoPlayer { } /// Set if the audio is muted or not, without changing the volume. - pub fn set_muted(&mut self, mute: bool) { - self.source.set_property("mute", &mute).unwrap(); + pub fn set_muted(&mut self, muted: bool) { + self.muted = muted; + self.source.set_property("mute", &muted).unwrap(); } /// Get if the audio is muted or not. pub fn muted(&self) -> bool { - // guaranteed to be a boolean - self.source - .get_property("mute") - .unwrap() - .get() - .unwrap() - .unwrap() + self.muted } /// Set if the media is paused or not. pub fn set_paused(&mut self, pause: bool) { - self.pause = pause; + self.paused = pause; self.source .set_state(if pause { gst::State::Paused @@ -212,24 +240,18 @@ impl VideoPlayer { /// Get if the media is paused or not. pub fn paused(&self) -> bool { - self.pause + self.paused } - /// Jumps to a specific time in the media. + /// Jumps to a specific position in the media. /// The seeking is not perfectly accurate. - /// - /// The position is converted to nanoseconds, so any duration with values more significant that nanoseconds is truncated. - pub fn seek(&mut self, position: std::time::Duration) -> Result<(), Error> { - self.source.seek_simple( - gst::SeekFlags::empty(), - gst::GenericFormattedValue::Time(gst::ClockTime::from_nseconds( - position.as_nanos() as _ - )), - )?; + pub fn seek(&mut self, position: impl Into) -> Result<(), Error> { + self.source + .seek_simple(gst::SeekFlags::FLUSH, position.into())?; Ok(()) } - /// Get the current playback position. + /// Get the current playback position in time. pub fn position(&self) -> Option { std::time::Duration::from_nanos( self.source @@ -257,7 +279,7 @@ impl VideoPlayer { } pub fn subscription(&self) -> Subscription { - if !self.pause { + if !self.paused { time::every(Duration::from_secs_f64(0.5 / self.framerate)) .map(|_| VideoPlayerMessage::NextFrame) } else { @@ -280,6 +302,7 @@ impl VideoPlayer { } } +// until iced 0.2 is released, which has this built-in mod time { use iced::futures;