From 1b78d221b6bb2f23d6275b52bfc2ff898d5b088e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 14 Jun 2018 02:17:43 +0300 Subject: [PATCH] PlayerWidget: Wire the play and pause buttons and add style classes to the Info Labels. This also includes the yak shaving of a ::new and ::inti methods. --- hammond-gtk/resources/gtk/player_toolbar.ui | 15 +++- hammond-gtk/resources/gtk/style.css | 9 ++- hammond-gtk/src/app.rs | 7 +- hammond-gtk/src/widgets/episode.rs | 24 ++---- hammond-gtk/src/widgets/player.rs | 81 +++++++++++++++++++-- 5 files changed, 103 insertions(+), 33 deletions(-) diff --git a/hammond-gtk/resources/gtk/player_toolbar.ui b/hammond-gtk/resources/gtk/player_toolbar.ui index 57c623c..1ae5620 100644 --- a/hammond-gtk/resources/gtk/player_toolbar.ui +++ b/hammond-gtk/resources/gtk/player_toolbar.ui @@ -39,7 +39,6 @@ True False - center 42 @@ -60,7 +59,6 @@ 60 - False True True Play @@ -77,7 +75,6 @@ 60 True - False True True Play @@ -124,7 +121,7 @@ True False - 42 + 24 image-x-generic-symbolic @@ -137,12 +134,18 @@ True False + True + center + center vertical True False Show Title + False @@ -155,6 +158,9 @@ True False Episode Title + False @@ -178,6 +184,7 @@ True True + center True True False diff --git a/hammond-gtk/resources/gtk/style.css b/hammond-gtk/resources/gtk/style.css index cfb0ecd..b4d2284 100644 --- a/hammond-gtk/resources/gtk/style.css +++ b/hammond-gtk/resources/gtk/style.css @@ -10,6 +10,11 @@ list, border { border-radius: 4px; } -.playback { - border-top: 1px solid @borders; +.player-show-label { + font-weight: bold; + font-size: smaller; } + +.player-episode-label { + font-size: smaller; +} \ No newline at end of file diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 7d041f0..27e7d2e 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -53,7 +53,7 @@ pub enum Action { MarkAllPlayerNotification(Arc), RemoveShow(Arc), ErrorNotification(String), - PlayEpisode(String), + InitEpisode(i32), } #[derive(Debug)] @@ -119,8 +119,7 @@ impl App { // Add the overlay to the main Box wrap.add(&overlay); - // FIXME: this should have a ::new() method instead. - let player = PlayerWidget::default(); + let player = PlayerWidget::new(); // Add the player to the main Box wrap.add(&player.action_bar); // player.reveal(); @@ -208,7 +207,7 @@ impl App { || {}, UndoState::Hidden); notif.show(&overlay); }, - Ok(Action::PlayEpisode(_uri)) => (), + Ok(Action::InitEpisode(rowid)) => player.initialize_episode(rowid).unwrap(), Err(_) => (), } diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 3da53fc..1af0531 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -1,4 +1,3 @@ -use gio::{File, FileExt}; use glib; use gtk; use gtk::prelude::*; @@ -18,7 +17,6 @@ use hammond_data::EpisodeWidgetQuery; use app::Action; use manager; -use std::path::Path; use std::rc::Rc; use std::sync::{Arc, Mutex, TryLockError}; @@ -444,26 +442,18 @@ fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: &Sender) -> Resu } fn on_play_bttn_clicked( - widget: &Rc, + _widget: &Rc, episode: &mut EpisodeWidgetQuery, sender: &Sender, ) -> Result<(), Error> { - let uri = dbqueries::get_episode_local_uri_from_id(episode.rowid())? - .ok_or_else(|| format_err!("Expected Some found None."))?; - let p = Path::new(&uri); - if p.exists() { - info!("Opening {}", uri); - // uri is actually a path, convert it (hacky) - let uri = File::new_for_path(p).get_uri().expect("Bad file path"); - sender.send(Action::PlayEpisode(uri)).ok(); - } else { - bail!("File \"{}\" does not exist.", uri); - } - - widget.info.set_title(&episode); sender - .send(Action::RefreshEpisodesViewBGR) + .send(Action::InitEpisode(episode.rowid())) .map_err(From::from) + + // widget.info.set_title(&episode); + // sender + // .send(Action::RefreshEpisodesViewBGR) + // .map_err(From::from) } // fn open_uri(rowid: i32) -> Result<(), Error> { diff --git a/hammond-gtk/src/widgets/player.rs b/hammond-gtk/src/widgets/player.rs index d021fba..1531b27 100644 --- a/hammond-gtk/src/widgets/player.rs +++ b/hammond-gtk/src/widgets/player.rs @@ -1,5 +1,7 @@ #![allow(warnings)] +use gio::{File, FileExt}; + use gstreamer::ClockTime; use gstreamer_player as gst; use gtk; @@ -7,6 +9,14 @@ use gtk::prelude::*; use failure::Error; +use hammond_data::dbqueries; +use hammond_data::{EpisodeWidgetQuery, PodcastCoverQuery}; + +use utils::set_image_from_path; + +use std::path::Path; +use std::rc::Rc; + pub trait PlayerExt { fn play(&self); fn pause(&self); @@ -26,8 +36,25 @@ struct PlayerInfo { } impl PlayerInfo { - fn init(&self) -> Result<(), Error> { - unimplemented!() + // FIXME: create a Diesel Model of the joined episode and podcast query instead + fn init(&self, episode: &EpisodeWidgetQuery, podcast: &PodcastCoverQuery) { + self.set_cover_image(podcast); + self.set_show_title(podcast); + self.set_episode_title(episode); + } + + fn set_episode_title(&self, episode: &EpisodeWidgetQuery) { + self.episode.set_text(&episode.title()); + } + + fn set_show_title(&self, show: &PodcastCoverQuery) { + self.show.set_text(&show.title()); + } + + fn set_cover_image(&self, show: &PodcastCoverQuery) { + set_image_from_path(&self.cover, show.id(), 24) + .map_err(|err| error!("Player Cover: {}", err)) + .ok(); } } @@ -123,9 +150,51 @@ impl Default for PlayerWidget { } impl PlayerWidget { + pub fn new() -> Rc { + let w = Rc::new(Self::default()); + Self::init(&w); + w + } + + fn init(s: &Rc) { + // Connect the play button to the gst Player. + s.controls.play.connect_clicked(clone!(s => move |_| s.play())); + + // Connect the pause button to the gst Player. + s.controls.pause.connect_clicked(clone!(s => move |_| s.pause())); + } + fn reveal(&self) { self.action_bar.show(); } + + pub fn initialize_episode(&self, rowid: i32) -> Result<(), Error> { + let ep = dbqueries::get_episode_widget_from_rowid(rowid)?; + let pd = dbqueries::get_podcast_cover_from_id(ep.podcast_id())?; + + self.info.init(&ep, &pd); + // Currently that will always be the case since the play button is + // only shown if the file is downloaded + if let Some(ref path) = ep.local_uri() { + if Path::new(path).exists() { + // path is an absolute fs path ex. "foo/bar/baz". + // Convert it so it will have a "file:///" + // FIXME: convert it properly + let uri = File::new_for_path(path).get_uri().expect("Bad file path"); + + // FIXME: Should also reset/flush the pipeline and then add the file + + // play the file + self.player.set_uri(&uri); + self.play(); + return Ok(()); + } + // TODO: log an error + } + + // Stream stuff + unimplemented!() + } } impl PlayerExt for PlayerWidget { @@ -135,8 +204,8 @@ impl PlayerExt for PlayerWidget { self.reveal(); - self.controls.pause.hide(); - self.controls.play.show(); + self.controls.pause.show(); + self.controls.play.hide(); self.player.play(); } @@ -145,8 +214,8 @@ impl PlayerExt for PlayerWidget { // assert the state is paused // TODO: assert!() - self.controls.pause.show(); - self.controls.play.hide(); + self.controls.pause.hide(); + self.controls.play.show(); self.player.pause(); }