PlayerWidget: Refactor the position_changed/updated callback.

It now uses gst_player::Player::connect_position_updated callback
to send, cross threads, the `position` value to the gtk main loop
which then updates the widget.
This commit is contained in:
Jordan Petridis 2018-06-15 17:50:26 +03:00
parent da467b7837
commit 50b480ee23
2 changed files with 21 additions and 35 deletions

View File

@ -57,6 +57,7 @@ pub enum Action {
ErrorNotification(String), ErrorNotification(String),
InitEpisode(i32), InitEpisode(i32),
PlayerDurationChanged(ClockTime), PlayerDurationChanged(ClockTime),
PlayerPositionUpdated(ClockTime),
} }
#[derive(Debug)] #[derive(Debug)]
@ -212,6 +213,7 @@ impl App {
}, },
Ok(Action::InitEpisode(rowid)) => player.initialize_episode(rowid).unwrap(), Ok(Action::InitEpisode(rowid)) => player.initialize_episode(rowid).unwrap(),
Ok(Action::PlayerDurationChanged(clock)) => player.on_duration_changed(clock), Ok(Action::PlayerDurationChanged(clock)) => player.on_duration_changed(clock),
Ok(Action::PlayerPositionUpdated(clock)) => player.on_position_updated(clock),
Err(_) => (), Err(_) => (),
} }

View File

@ -1,15 +1,16 @@
// #![allow(warnings)] // #![allow(warnings)]
use gio::{File, FileExt}; // use gst;
use glib::SignalHandlerId;
use gst;
use gst::prelude::*; use gst::prelude::*;
use gst::ClockTime; use gst::ClockTime;
use gst_player; use gst_player;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
use gio::{File, FileExt};
use glib::SignalHandlerId;
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use failure::Error; use failure::Error;
// use send_cell::SendCell; // use send_cell::SendCell;
@ -202,7 +203,11 @@ impl PlayerWidget {
.ok(); .ok();
})); }));
Self::connect_timers(s); s.player.connect_position_updated(clone!(sender => move |_, position| {
sender.send(Action::PlayerPositionUpdated(position))
.map_err(|err| error!("Error: {}", err))
.ok();
}));
} }
fn reveal(&self) { fn reveal(&self) {
@ -237,22 +242,6 @@ impl PlayerWidget {
unimplemented!() unimplemented!()
} }
// FIXME: Refactor to use gst_player::Player instead of raw pipeline.
// FIXME: Refactor the labels to use some kind of Human™ time/values.
// Adapted from https://github.com/sdroege/gstreamer-rs/blob/f4d57a66522183d4927b47af422e8f321182111f/tutorials/src/bin/basic-tutorial-5.rs#L131-L164
fn connect_timers(s: &Rc<Self>) {
// Update the PlayerTimes
gtk::timeout_add(
250,
clone!(s => move || {
// TODO: use Player::connect_position_updated() instead
s.on_position_changed();
Continue(true)
}),
);
}
fn connect_update_slider(slider: &gtk::Scale, player: &gst_player::Player) -> SignalHandlerId { fn connect_update_slider(slider: &gtk::Scale, player: &gst_player::Player) -> SignalHandlerId {
slider.connect_value_changed(clone!(player => move |slider| { slider.connect_value_changed(clone!(player => move |slider| {
let value = slider.get_value() as u64; let value = slider.get_value() as u64;
@ -275,23 +264,18 @@ impl PlayerWidget {
.set_text(&format!("{:.2}", seconds / 60.0)); .set_text(&format!("{:.2}", seconds / 60.0));
} }
/// Update the `gtk::SclaeBar` when the pipeline position is changed.. /// Update the `gtk::SclaeBar` when the pipeline position is changed.
fn on_position_changed(&self) { pub fn on_position_updated(&self, position: ClockTime) {
let pipeline = &self.player.get_pipeline();
let slider = &self.timer.slider; let slider = &self.timer.slider;
let seconds = position.seconds().map(|v| v as f64).unwrap_or(0.0);
if let Some(pos) = pipeline.query_position::<ClockTime>() { slider.block_signal(&self.timer.slider_update);
let seconds = pos / gst::SECOND; slider.set_value(seconds);
let seconds = seconds.map(|v| v as f64).unwrap_or(0.0); slider.unblock_signal(&self.timer.slider_update);
slider.block_signal(&self.timer.slider_update); self.timer
slider.set_value(seconds); .progressed
slider.unblock_signal(&self.timer.slider_update); .set_text(&format!("{:.2}", seconds / 60.0));
self.timer
.progressed
.set_text(&format!("{:.2}", seconds / 60.0));
}
} }
} }