diff --git a/hammond-gtk/resources/gtk/playback.ui b/hammond-gtk/resources/gtk/playback.ui
index 0457d68..8f32958 100644
--- a/hammond-gtk/resources/gtk/playback.ui
+++ b/hammond-gtk/resources/gtk/playback.ui
@@ -28,7 +28,7 @@
6
- 3
+ 1
0
2
@@ -46,13 +46,14 @@
right
- 1
+ 2
1
2
-
@@ -92,7 +93,7 @@
label
- 2
+ 3
0
@@ -100,4 +101,4 @@
-
+
\ No newline at end of file
diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs
index 4789b06..c2e04c3 100644
--- a/hammond-gtk/src/app.rs
+++ b/hammond-gtk/src/app.rs
@@ -6,6 +6,7 @@ use gio::{
};
use glib;
use gstreamer_player as gst;
+use gstreamer::ClockTime;
use gtk;
use gtk::prelude::*;
use gtk::SettingsExt as GtkSettingsExt;
@@ -40,7 +41,10 @@ pub enum Action {
MarkAllPlayerNotification(Arc),
RemoveShow(Arc),
ErrorNotification(String),
- PlayEpisode(String)
+ PlayEpisode(String),
+ PlayerStateChanged(gst::PlayerState),
+ PlayerMediaChanged(Option, ClockTime),
+ PlayerPositionChanged(ClockTime),
}
#[derive(Debug)]
@@ -104,11 +108,8 @@ impl App {
// Add the overlay to the main window
wrap.add(&overlay);
- let playback = Playback::new();
-
- let reveal = gtk::Revealer::new();
- reveal.add(&playback.container);
- wrap.add(&reveal);
+ let playback = Rc::new(Playback::new());
+ wrap.add(playback.get_widget());
WindowGeometry::from_settings(&settings).apply(&window);
@@ -123,8 +124,20 @@ impl App {
sender.send(Action::ErrorNotification(format!("Playback: {}", err))).ok();
}));
+ player.connect_state_changed(clone!(sender => move |_,state| {
+ sender.send(Action::PlayerStateChanged(state)).ok();
+ }));
+
+ player.connect_media_info_updated(clone!(sender => move |_,info| {
+ sender.send(Action::PlayerMediaChanged(info.get_title(), info.get_duration())).ok();
+ }));
+
+ player.connect_property_position_notify(clone!(sender => move |p| {
+ sender.send(Action::PlayerPositionChanged(p.get_position())).ok();
+ }));
+
gtk::timeout_add(50, clone!(sender, receiver => move || {
- // Uses receiver, content, header, sender, overlay
+ // Uses receiver, content, header, sender, overlay, playback
match receiver.try_recv() {
Ok(Action::RefreshAllViews) => content.update(),
Ok(Action::RefreshShowsView) => content.update_shows_view(),
@@ -185,6 +198,9 @@ impl App {
player.set_uri(&uri);
player.play();
},
+ Ok(Action::PlayerStateChanged(state)) => playback.state_changed(state),
+ Ok(Action::PlayerMediaChanged(t, l)) => playback.media_changed(t, l),
+ Ok(Action::PlayerPositionChanged(t)) => playback.position_changed(t),
Err(_) => (),
}
diff --git a/hammond-gtk/src/widgets/playback.rs b/hammond-gtk/src/widgets/playback.rs
index 7ec6d4e..becef5b 100644
--- a/hammond-gtk/src/widgets/playback.rs
+++ b/hammond-gtk/src/widgets/playback.rs
@@ -1,16 +1,32 @@
+use gstreamer::ClockTime;
+use gstreamer_player as gst;
use gtk;
+use gtk::prelude::*;
#[derive(Debug, Clone)]
pub struct Playback {
- pub container: gtk::Grid,
+ reveal: gtk::Revealer,
+ container: gtk::Grid,
+ play: gtk::Button,
+ seek: gtk::Scale,
+ title: gtk::Label,
+ time: gtk::Label,
}
impl Default for Playback {
fn default() -> Self {
let builder = gtk::Builder::new_from_resource("/org/gnome/Hammond/gtk/playback.ui");
let container = builder.get_object("wrapper").unwrap();
+ let play = builder.get_object("play").unwrap();
+ let seek = builder.get_object("seek").unwrap();
+ let title = builder.get_object("title").unwrap();
+ let time = builder.get_object("time").unwrap();
- Playback { container }
+ let reveal = gtk::Revealer::new();
+ reveal.set_no_show_all(true);
+ reveal.add(&container);
+
+ Playback { reveal, container, play, seek, title, time }
}
}
@@ -18,4 +34,61 @@ impl Playback {
pub fn new() -> Playback {
Playback::default()
}
+
+ pub fn set_icon(&self, icon: &str) {
+ let image = gtk::Image::new_from_icon_name(icon, gtk::IconSize::Button.into());
+ self.play.set_image(Some(&image));
+ }
+
+ pub fn get_widget(&self) -> >k::Revealer {
+ &self.reveal
+ }
+
+ pub fn state_changed(&self, state: gst::PlayerState) {
+ // Once the playback controls are shown they don't go
+ // away again so show them unconditionally
+ self.reveal.show();
+ self.reveal.set_reveal_child(true);
+ match state {
+ gst::PlayerState::Buffering => {
+ println!("Buffering!!!!!!!");
+ },
+ gst::PlayerState::Stopped | gst::PlayerState::Paused => {
+ println!("Stopped/Paused");
+ self.set_icon("media-playback-start-symbolic");
+ },
+ gst::PlayerState::Playing => {
+ println!("Playing");
+ self.set_icon("media-playback-pause-symbolic");
+ },
+ _ => {
+ println!("Weird stuff");
+ }
+ }
+ }
+
+ pub fn media_changed(&self, title: Option, length: ClockTime) {
+ self.reveal.show();
+ self.reveal.set_reveal_child(true);
+ if let Some(title) = title {
+ self.title.set_label(&title);
+ } else {
+ self.title.set_label("");
+ }
+ if let Some(s) = length.seconds() {
+ let hours = s / 3600;
+ let s = s - (hours * 3600);
+ let mins = s / 60;
+ let s = s - (mins * 60);
+ // This is a little nasty
+ let t = format!("{}:{}:{}", hours, mins, s);
+ self.time.set_label(&t);
+ } else {
+ self.time.set_label("");
+ }
+ }
+
+ pub fn position_changed(&self, _pos: ClockTime) {
+ println!("Tada!");
+ }
}