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.
This commit is contained in:
parent
67f14397f8
commit
5a36eb1ac4
@ -39,7 +39,6 @@
|
||||
<object class="GtkBox" id="buttons">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="rewind_button">
|
||||
<property name="width_request">42</property>
|
||||
@ -60,7 +59,6 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="play_button">
|
||||
<property name="width_request">60</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Play</property>
|
||||
@ -77,7 +75,6 @@
|
||||
<object class="GtkButton" id="pause_button">
|
||||
<property name="width_request">60</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Play</property>
|
||||
@ -124,7 +121,7 @@
|
||||
<object class="GtkImage" id="show_cover">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="pixel_size">42</property>
|
||||
<property name="pixel_size">24</property>
|
||||
<property name="icon_name">image-x-generic-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
@ -137,12 +134,18 @@
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="show_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Show Title</property>
|
||||
<style>
|
||||
<class name="player-show-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@ -155,6 +158,9 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Episode Title</property>
|
||||
<style>
|
||||
<class name="player-episode-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@ -178,6 +184,7 @@
|
||||
<object class="GtkScale" id="seek">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="show_fill_level">True</property>
|
||||
<property name="restrict_to_fill_level">False</property>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -53,7 +53,7 @@ pub enum Action {
|
||||
MarkAllPlayerNotification(Arc<Podcast>),
|
||||
RemoveShow(Arc<Podcast>),
|
||||
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(_) => (),
|
||||
}
|
||||
|
||||
|
||||
@ -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<Action>) -> Resu
|
||||
}
|
||||
|
||||
fn on_play_bttn_clicked(
|
||||
widget: &Rc<EpisodeWidget>,
|
||||
_widget: &Rc<EpisodeWidget>,
|
||||
episode: &mut EpisodeWidgetQuery,
|
||||
sender: &Sender<Action>,
|
||||
) -> 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> {
|
||||
|
||||
@ -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<Self> {
|
||||
let w = Rc::new(Self::default());
|
||||
Self::init(&w);
|
||||
w
|
||||
}
|
||||
|
||||
fn init(s: &Rc<Self>) {
|
||||
// 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();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user