PlayerWidget: Use the Gtk Main Context for the gst_player as well.
There is no longer a need for sending stuff to the main-thread `Action` channel anymore thanks to this.
This commit is contained in:
parent
0686fca3b0
commit
eeef0d13ff
@ -5,7 +5,6 @@ use gio::{
|
|||||||
SimpleAction, SimpleActionExt,
|
SimpleAction, SimpleActionExt,
|
||||||
};
|
};
|
||||||
use glib;
|
use glib;
|
||||||
use gst_player;
|
|
||||||
use gtk;
|
use gtk;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::SettingsExt as GtkSettingsExt;
|
use gtk::SettingsExt as GtkSettingsExt;
|
||||||
@ -19,7 +18,6 @@ use stacks::{Content, PopulatedState};
|
|||||||
use utils;
|
use utils;
|
||||||
use widgets::appnotif::{InAppNotification, UndoState};
|
use widgets::appnotif::{InAppNotification, UndoState};
|
||||||
use widgets::player;
|
use widgets::player;
|
||||||
use widgets::player::PlayerExt;
|
|
||||||
use widgets::{about_dialog, mark_all_notif, remove_show_notif};
|
use widgets::{about_dialog, mark_all_notif, remove_show_notif};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -57,9 +55,6 @@ pub enum Action {
|
|||||||
RemoveShow(Arc<Podcast>),
|
RemoveShow(Arc<Podcast>),
|
||||||
ErrorNotification(String),
|
ErrorNotification(String),
|
||||||
InitEpisode(i32),
|
InitEpisode(i32),
|
||||||
PlayerDurationChanged(player::Duration),
|
|
||||||
PlayerPositionUpdated(player::Position),
|
|
||||||
PlayerEndofStream(gst_player::Player),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -138,7 +133,7 @@ impl App {
|
|||||||
window.show_all();
|
window.show_all();
|
||||||
window.activate();
|
window.activate();
|
||||||
|
|
||||||
gtk::timeout_add(15, clone!(sender, receiver => move || {
|
gtk::timeout_add(25, clone!(sender, receiver => move || {
|
||||||
// Uses receiver, content, header, sender, overlay, playback
|
// Uses receiver, content, header, sender, overlay, playback
|
||||||
match receiver.try_recv() {
|
match receiver.try_recv() {
|
||||||
Ok(Action::RefreshAllViews) => content.update(),
|
Ok(Action::RefreshAllViews) => content.update(),
|
||||||
@ -196,9 +191,6 @@ impl App {
|
|||||||
notif.show(&overlay);
|
notif.show(&overlay);
|
||||||
},
|
},
|
||||||
Ok(Action::InitEpisode(rowid)) => player.initialize_episode(rowid).unwrap(),
|
Ok(Action::InitEpisode(rowid)) => player.initialize_episode(rowid).unwrap(),
|
||||||
Ok(Action::PlayerDurationChanged(dur)) => player.timer.on_duration_changed(dur),
|
|
||||||
Ok(Action::PlayerPositionUpdated(pos)) => player.timer.on_position_updated(pos),
|
|
||||||
Ok(Action::PlayerEndofStream(_)) => player.stop(),
|
|
||||||
Err(_) => (),
|
Err(_) => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ use glib::SignalHandlerId;
|
|||||||
use chrono::NaiveTime;
|
use chrono::NaiveTime;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use send_cell::SendCell;
|
||||||
|
|
||||||
use hammond_data::{dbqueries, USER_AGENT};
|
use hammond_data::{dbqueries, USER_AGENT};
|
||||||
use hammond_data::{EpisodeWidgetQuery, PodcastCoverQuery};
|
use hammond_data::{EpisodeWidgetQuery, PodcastCoverQuery};
|
||||||
@ -23,12 +24,12 @@ use std::path::Path;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum SeekDirection {
|
enum SeekDirection {
|
||||||
Backwards,
|
Backwards,
|
||||||
Forward,
|
Forward,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlayerExt {
|
trait PlayerExt {
|
||||||
fn play(&self);
|
fn play(&self);
|
||||||
fn pause(&self);
|
fn pause(&self);
|
||||||
fn stop(&self);
|
fn stop(&self);
|
||||||
@ -72,7 +73,7 @@ impl PlayerInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PlayerTimes {
|
struct PlayerTimes {
|
||||||
container: gtk::Box,
|
container: gtk::Box,
|
||||||
progressed: gtk::Label,
|
progressed: gtk::Label,
|
||||||
duration: gtk::Label,
|
duration: gtk::Label,
|
||||||
@ -82,7 +83,7 @@ pub struct PlayerTimes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Duration(ClockTime);
|
struct Duration(ClockTime);
|
||||||
|
|
||||||
impl Deref for Duration {
|
impl Deref for Duration {
|
||||||
type Target = ClockTime;
|
type Target = ClockTime;
|
||||||
@ -92,7 +93,7 @@ impl Deref for Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Position(ClockTime);
|
struct Position(ClockTime);
|
||||||
|
|
||||||
impl Deref for Position {
|
impl Deref for Position {
|
||||||
type Target = ClockTime;
|
type Target = ClockTime;
|
||||||
@ -159,14 +160,19 @@ pub struct PlayerWidget {
|
|||||||
pub action_bar: gtk::ActionBar,
|
pub action_bar: gtk::ActionBar,
|
||||||
player: gst_player::Player,
|
player: gst_player::Player,
|
||||||
controls: PlayerControls,
|
controls: PlayerControls,
|
||||||
pub timer: PlayerTimes,
|
timer: PlayerTimes,
|
||||||
info: PlayerInfo,
|
info: PlayerInfo,
|
||||||
rate: PlayerRate,
|
rate: PlayerRate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlayerWidget {
|
impl Default for PlayerWidget {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let player = gst_player::Player::new(None, None);
|
let dispatcher = gst_player::PlayerGMainContextSignalDispatcher::new(None);
|
||||||
|
let player = gst_player::Player::new(
|
||||||
|
None,
|
||||||
|
// Use the gtk main thread
|
||||||
|
Some(&dispatcher.upcast::<gst_player::PlayerSignalDispatcher>()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut config = player.get_config();
|
let mut config = player.get_config();
|
||||||
config.set_user_agent(USER_AGENT);
|
config.set_user_agent(USER_AGENT);
|
||||||
@ -250,40 +256,10 @@ impl PlayerWidget {
|
|||||||
w
|
w
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
||||||
fn init(s: &Rc<Self>, sender: &Sender<Action>) {
|
fn init(s: &Rc<Self>, sender: &Sender<Action>) {
|
||||||
Self::connect_control_buttons(s);
|
Self::connect_control_buttons(s);
|
||||||
Self::connect_rate_buttons(s);
|
Self::connect_rate_buttons(s);
|
||||||
|
Self::connect_gst_signals(s, sender);
|
||||||
// Log gst warnings.
|
|
||||||
s.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
|
|
||||||
|
|
||||||
// Log gst errors.
|
|
||||||
s.player.connect_error(clone!(sender => move |_, error| {
|
|
||||||
// FIXME: should never occur and should not be user facing.
|
|
||||||
sender.send(Action::ErrorNotification(format!("Player Error: {}", error)))
|
|
||||||
.map_err(|err| error!("Error: {}", err))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.player.connect_duration_changed(clone!(sender => move |_, clock| {
|
|
||||||
sender.send(Action::PlayerDurationChanged(Duration(clock)))
|
|
||||||
.map_err(|err| error!("Error: {}", err))
|
|
||||||
.ok();
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.player.connect_position_updated(clone!(sender => move |_, clock| {
|
|
||||||
sender.send(Action::PlayerPositionUpdated(Position(clock)))
|
|
||||||
.map_err(|err| error!("Error: {}", err))
|
|
||||||
.ok();
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.player.connect_end_of_stream(clone!(sender => move |player| {
|
|
||||||
sender.send(Action::PlayerEndofStream(player.clone()))
|
|
||||||
.map_err(|err| error!("Error: {}", err))
|
|
||||||
.ok();
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
@ -302,6 +278,37 @@ impl PlayerWidget {
|
|||||||
s.controls.forward.connect_clicked(clone!(s => move |_| s.fast_forward()));
|
s.controls.forward.connect_clicked(clone!(s => move |_| s.fast_forward()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
fn connect_gst_signals(s: &Rc<Self>, sender: &Sender<Action>) {
|
||||||
|
// Log gst warnings.
|
||||||
|
s.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
|
||||||
|
|
||||||
|
// Log gst errors.
|
||||||
|
s.player.connect_error(clone!(sender => move |_, error| {
|
||||||
|
// FIXME: should never occur and should not be user facing.
|
||||||
|
sender.send(Action::ErrorNotification(format!("Player Error: {}", error)))
|
||||||
|
.map_err(|err| error!("Error: {}", err))
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
// The followign callbacks require `Send` but are handled by the gtk main loop
|
||||||
|
let s2 = SendCell::new(s.clone());
|
||||||
|
|
||||||
|
// Update the duration label and the slider
|
||||||
|
s.player.connect_duration_changed(clone!(s2 => move |_, clock| {
|
||||||
|
s2.borrow().timer.on_duration_changed(Duration(clock));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update the position label and the slider
|
||||||
|
s.player.connect_position_updated(clone!(s2 => move |_, clock| {
|
||||||
|
s2.borrow().timer.on_position_updated(Position(clock));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Reset the slider to 0 and show a play button
|
||||||
|
s.player.connect_end_of_stream(clone!(s2 => move |_| s2.borrow().stop()));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
fn connect_rate_buttons(s: &Rc<Self>) {
|
fn connect_rate_buttons(s: &Rc<Self>) {
|
||||||
s.rate.radio_normal.connect_toggled(clone!(s => move |_| s.on_rate_changed(1.00)));
|
s.rate.radio_normal.connect_toggled(clone!(s => move |_| s.on_rate_changed(1.00)));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user