diff --git a/hammond-gtk/resources/gtk/player_toolbar.ui b/hammond-gtk/resources/gtk/player_toolbar.ui index bea3fc4..d766706 100644 --- a/hammond-gtk/resources/gtk/player_toolbar.ui +++ b/hammond-gtk/resources/gtk/player_toolbar.ui @@ -250,9 +250,122 @@ + + 3 + + + + + True + True + True + center + center + 6 + up + rate_popover + + + True + False + 6 + + + True + False + 1.00x + + + False + True + 0 + + + + + True + False + go-down-symbolic + 1 + + + False + True + 1 + + + + + 4 + + False + rate_button + + + True + False + vertical + 3 + start + + + 1.50x + True + True + False + center + center + True + True + normal_rate + + + True + True + 0 + + + + + 1.25x + True + True + False + center + center + True + True + normal_rate + + + True + True + 1 + + + + + 1.00x + True + True + False + center + center + True + True + + + True + True + 2 + + + + + diff --git a/hammond-gtk/src/widgets/player.rs b/hammond-gtk/src/widgets/player.rs index 5368167..eaa28d2 100644 --- a/hammond-gtk/src/widgets/player.rs +++ b/hammond-gtk/src/widgets/player.rs @@ -35,8 +35,7 @@ pub trait PlayerExt { fn seek(&self, offset: ClockTime, direction: SeekDirection); fn fast_forward(&self); fn rewind(&self); - // TODO: change playback rate - // fn set_playback_rate(&self); + fn set_playback_rate(&self, f64); } #[derive(Debug, Clone)] @@ -136,6 +135,16 @@ fn format_duration(seconds: u32) -> String { } } +#[derive(Debug, Clone)] +struct PlayerRate { + radio150: gtk::RadioButton, + radio125: gtk::RadioButton, + radio_normal: gtk::RadioButton, + popover: gtk::Popover, + btn: gtk::MenuButton, + label: gtk::Label, +} + #[derive(Debug, Clone)] struct PlayerControls { container: gtk::Box, @@ -152,6 +161,7 @@ pub struct PlayerWidget { controls: PlayerControls, pub timer: PlayerTimes, info: PlayerInfo, + rate: PlayerRate, } impl Default for PlayerWidget { @@ -207,12 +217,28 @@ impl Default for PlayerWidget { cover, }; + let radio150 = builder.get_object("rate_1_50").unwrap(); + let radio125 = builder.get_object("rate_1_25").unwrap(); + let radio_normal = builder.get_object("normal_rate").unwrap(); + let popover = builder.get_object("rate_popover").unwrap(); + let btn = builder.get_object("rate_button").unwrap(); + let label = builder.get_object("rate_label").unwrap(); + let rate = PlayerRate { + radio150, + radio125, + radio_normal, + popover, + label, + btn, + }; + PlayerWidget { player, action_bar, controls, timer, info, + rate, } } } @@ -226,7 +252,8 @@ impl PlayerWidget { #[cfg_attr(rustfmt, rustfmt_skip)] fn init(s: &Rc, sender: &Sender) { - Self::connect_buttons(s); + Self::connect_control_buttons(s); + Self::connect_rate_buttons(s); // Log gst warnings. s.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn)); @@ -261,7 +288,7 @@ impl PlayerWidget { #[cfg_attr(rustfmt, rustfmt_skip)] /// Connect the `PlayerControls` buttons to the `PlayerExt` methods. - fn connect_buttons(s: &Rc) { + fn connect_control_buttons(s: &Rc) { // Connect the play button to the gst Player. s.controls.play.connect_clicked(clone!(s => move |_| s.play())); @@ -275,6 +302,18 @@ impl PlayerWidget { s.controls.forward.connect_clicked(clone!(s => move |_| s.fast_forward())); } + #[cfg_attr(rustfmt, rustfmt_skip)] + fn connect_rate_buttons(s: &Rc) { + s.rate.radio_normal.connect_toggled(clone!(s => move |_| s.on_rate_changed(1.00))); + s.rate.radio125.connect_toggled(clone!(s => move |_| s.on_rate_changed(1.25))); + s.rate.radio150.connect_toggled(clone!(s => move |_| s.on_rate_changed(1.50))); + } + + fn on_rate_changed(&self, rate: f64) { + self.set_playback_rate(rate); + self.rate.label.set_text(&format!("{:.2}x", rate)); + } + fn reveal(&self) { self.action_bar.show(); } @@ -370,4 +409,8 @@ impl PlayerExt for PlayerWidget { fn fast_forward(&self) { self.seek(ClockTime::from_seconds(10), SeekDirection::Forward) } + + fn set_playback_rate(&self, rate: f64) { + self.player.set_rate(rate); + } }