Player: Use a wrapper struct to write methods on &self
Previously, methods that required the Player to be ref counted, were using static methods with s: &Rc<Self> as the first argument. Now the wrapper type auto-derefs to the inner struct and you can declare methods on just &self.
This commit is contained in:
parent
201f2e23c7
commit
98f105fda0
@ -96,7 +96,7 @@ pub(crate) struct App {
|
|||||||
settings: gio::Settings,
|
settings: gio::Settings,
|
||||||
content: Rc<Content>,
|
content: Rc<Content>,
|
||||||
headerbar: Rc<Header>,
|
headerbar: Rc<Header>,
|
||||||
player: Rc<player::PlayerWidget>,
|
player: player::PlayerWrapper,
|
||||||
updater: RefCell<Option<InAppNotification>>,
|
updater: RefCell<Option<InAppNotification>>,
|
||||||
sender: Sender<Action>,
|
sender: Sender<Action>,
|
||||||
receiver: Receiver<Action>,
|
receiver: Receiver<Action>,
|
||||||
@ -151,7 +151,7 @@ impl App {
|
|||||||
// Add the overlay to the main Box
|
// Add the overlay to the main Box
|
||||||
wrap.add(&overlay);
|
wrap.add(&overlay);
|
||||||
|
|
||||||
let player = player::PlayerWidget::new(&sender);
|
let player = player::PlayerWrapper::new(&sender);
|
||||||
// Add the player to the main Box
|
// Add the player to the main Box
|
||||||
wrap.add(&player.action_bar);
|
wrap.add(&player.action_bar);
|
||||||
|
|
||||||
|
|||||||
@ -304,136 +304,6 @@ impl Default for PlayerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PlayerWidget {
|
impl PlayerWidget {
|
||||||
pub(crate) fn new(sender: &Sender<Action>) -> Rc<Self> {
|
|
||||||
let w = Rc::new(Self::default());
|
|
||||||
Self::init(&w, sender);
|
|
||||||
w
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(s: &Rc<Self>, sender: &Sender<Action>) {
|
|
||||||
Self::connect_control_buttons(s);
|
|
||||||
Self::connect_rate_buttons(s);
|
|
||||||
Self::connect_mpris_buttons(s, sender);
|
|
||||||
Self::connect_gst_signals(s, sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect the `PlayerControls` buttons to the `PlayerExt` methods.
|
|
||||||
fn connect_control_buttons(s: &Rc<Self>) {
|
|
||||||
let weak = Rc::downgrade(s);
|
|
||||||
|
|
||||||
// Connect the play button to the gst Player.
|
|
||||||
s.controls.play.connect_clicked(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.play());
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Connect the pause button to the gst Player.
|
|
||||||
s.controls.pause.connect_clicked(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.pause());
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Connect the rewind button to the gst Player.
|
|
||||||
s.controls.rewind.connect_clicked(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.rewind());
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Connect the fast-forward button to the gst Player.
|
|
||||||
s.controls.forward.connect_clicked(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.fast_forward());
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn connect_mpris_buttons(s: &Rc<Self>, sender: &Sender<Action>) {
|
|
||||||
let weak = Rc::downgrade(s);
|
|
||||||
|
|
||||||
let mpris = s.info.mpris.clone();
|
|
||||||
s.info.mpris.connect_play_pause(clone!(weak => move || {
|
|
||||||
let player = match weak.upgrade() {
|
|
||||||
Some(s) => s,
|
|
||||||
None => return
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(status) = mpris.get_playback_status() {
|
|
||||||
match status.as_ref() {
|
|
||||||
"Paused" => player.play(),
|
|
||||||
"Stopped" => player.play(),
|
|
||||||
_ => player.pause(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.info.mpris.connect_next(clone!(weak => move || {
|
|
||||||
weak.upgrade().map(|p| p.fast_forward());
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.info.mpris.connect_previous(clone!(weak => move || {
|
|
||||||
weak.upgrade().map(|p| p.rewind());
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.info
|
|
||||||
.mpris
|
|
||||||
.connect_raise(clone!(sender => move || sender.send(Action::RaiseWindow)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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| {
|
|
||||||
// sender.send(Action::ErrorNotification(format!("Player Error: {}", error)));
|
|
||||||
let s = i18n("The media player was unable to execute an action.");
|
|
||||||
sender.send(Action::ErrorNotification(s));
|
|
||||||
}));
|
|
||||||
|
|
||||||
// The following callbacks require `Send` but are handled by the gtk main loop
|
|
||||||
let weak = Fragile::new(Rc::downgrade(s));
|
|
||||||
|
|
||||||
// Update the duration label and the slider
|
|
||||||
s.player.connect_duration_changed(clone!(weak => move |_, clock| {
|
|
||||||
weak.get()
|
|
||||||
.upgrade()
|
|
||||||
.map(|p| p.timer.on_duration_changed(Duration(clock)));
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Update the position label and the slider
|
|
||||||
s.player.connect_position_updated(clone!(weak => move |_, clock| {
|
|
||||||
weak.get()
|
|
||||||
.upgrade()
|
|
||||||
.map(|p| p.timer.on_position_updated(Position(clock)));
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Reset the slider to 0 and show a play button
|
|
||||||
s.player.connect_end_of_stream(clone!(weak => move |_| {
|
|
||||||
weak.get()
|
|
||||||
.upgrade()
|
|
||||||
.map(|p| p.stop());
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
||||||
fn connect_rate_buttons(s: &Rc<Self>) {
|
|
||||||
let weak = Rc::downgrade(s);
|
|
||||||
|
|
||||||
s.rate
|
|
||||||
.radio_normal
|
|
||||||
.connect_toggled(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.on_rate_changed(1.00));
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.rate
|
|
||||||
.radio125
|
|
||||||
.connect_toggled(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.on_rate_changed(1.25));
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.rate
|
|
||||||
.radio150
|
|
||||||
.connect_toggled(clone!(weak => move |_| {
|
|
||||||
weak.upgrade().map(|p| p.on_rate_changed(1.50));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_rate_changed(&self, rate: f64) {
|
fn on_rate_changed(&self, rate: f64) {
|
||||||
self.set_playback_rate(rate);
|
self.set_playback_rate(rate);
|
||||||
self.rate.label.set_text(&format!("{:.2}×", rate));
|
self.rate.label.set_text(&format!("{:.2}×", rate));
|
||||||
@ -593,3 +463,158 @@ impl PlayerExt for PlayerWidget {
|
|||||||
self.player.set_rate(rate);
|
self.player.set_rate(rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct PlayerWrapper(pub Rc<PlayerWidget>);
|
||||||
|
|
||||||
|
impl Default for PlayerWrapper {
|
||||||
|
fn default() -> Self {
|
||||||
|
PlayerWrapper(Rc::new(PlayerWidget::default()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for PlayerWrapper {
|
||||||
|
type Target = Rc<PlayerWidget>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayerWrapper {
|
||||||
|
pub(crate) fn new(sender: &Sender<Action>) -> Self {
|
||||||
|
let w = Self::default();
|
||||||
|
w.init(sender);
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(&self, sender: &Sender<Action>) {
|
||||||
|
self.connect_control_buttons();
|
||||||
|
self.connect_rate_buttons();
|
||||||
|
self.connect_mpris_buttons(sender);
|
||||||
|
self.connect_gst_signals(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect the `PlayerControls` buttons to the `PlayerExt` methods.
|
||||||
|
fn connect_control_buttons(&self) {
|
||||||
|
let weak = Rc::downgrade(self);
|
||||||
|
|
||||||
|
// Connect the play button to the gst Player.
|
||||||
|
self.controls.play.connect_clicked(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.play());
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Connect the pause button to the gst Player.
|
||||||
|
self.controls
|
||||||
|
.pause
|
||||||
|
.connect_clicked(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.pause());
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Connect the rewind button to the gst Player.
|
||||||
|
self.controls
|
||||||
|
.rewind
|
||||||
|
.connect_clicked(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.rewind());
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Connect the fast-forward button to the gst Player.
|
||||||
|
self.controls
|
||||||
|
.forward
|
||||||
|
.connect_clicked(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.fast_forward());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
fn connect_gst_signals(&self, sender: &Sender<Action>) {
|
||||||
|
// Log gst warnings.
|
||||||
|
self.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
|
||||||
|
|
||||||
|
// Log gst errors.
|
||||||
|
self.player.connect_error(clone!(sender => move |_, _error| {
|
||||||
|
// sender.send(Action::ErrorNotification(format!("Player Error: {}", error)));
|
||||||
|
let s = i18n("The media player was unable to execute an action.");
|
||||||
|
sender.send(Action::ErrorNotification(s));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// The following callbacks require `Send` but are handled by the gtk main loop
|
||||||
|
let weak = Fragile::new(Rc::downgrade(self));
|
||||||
|
|
||||||
|
// Update the duration label and the slider
|
||||||
|
self.player.connect_duration_changed(clone!(weak => move |_, clock| {
|
||||||
|
weak.get()
|
||||||
|
.upgrade()
|
||||||
|
.map(|p| p.timer.on_duration_changed(Duration(clock)));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update the position label and the slider
|
||||||
|
self.player.connect_position_updated(clone!(weak => move |_, clock| {
|
||||||
|
weak.get()
|
||||||
|
.upgrade()
|
||||||
|
.map(|p| p.timer.on_position_updated(Position(clock)));
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Reset the slider to 0 and show a play button
|
||||||
|
self.player.connect_end_of_stream(clone!(weak => move |_| {
|
||||||
|
weak.get()
|
||||||
|
.upgrade()
|
||||||
|
.map(|p| p.stop());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
fn connect_rate_buttons(&self) {
|
||||||
|
let weak = Rc::downgrade(self);
|
||||||
|
|
||||||
|
self.rate
|
||||||
|
.radio_normal
|
||||||
|
.connect_toggled(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.on_rate_changed(1.00));
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.rate
|
||||||
|
.radio125
|
||||||
|
.connect_toggled(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.on_rate_changed(1.25));
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.rate
|
||||||
|
.radio150
|
||||||
|
.connect_toggled(clone!(weak => move |_| {
|
||||||
|
weak.upgrade().map(|p| p.on_rate_changed(1.50));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_mpris_buttons(&self, sender: &Sender<Action>) {
|
||||||
|
let weak = Rc::downgrade(self);
|
||||||
|
|
||||||
|
// FIXME: Refference cycle with mpris
|
||||||
|
let mpris = self.info.mpris.clone();
|
||||||
|
self.info.mpris.connect_play_pause(clone!(weak => move || {
|
||||||
|
let player = match weak.upgrade() {
|
||||||
|
Some(s) => s,
|
||||||
|
None => return
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(status) = mpris.get_playback_status() {
|
||||||
|
match status.as_ref() {
|
||||||
|
"Paused" => player.play(),
|
||||||
|
"Stopped" => player.play(),
|
||||||
|
_ => player.pause(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.info.mpris.connect_next(clone!(weak => move || {
|
||||||
|
weak.upgrade().map(|p| p.fast_forward());
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.info.mpris.connect_previous(clone!(weak => move || {
|
||||||
|
weak.upgrade().map(|p| p.rewind());
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.info
|
||||||
|
.mpris
|
||||||
|
.connect_raise(clone!(sender => move || sender.send(Action::RaiseWindow)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user