From a6378b281a066eb8b7a0c1eec0d2bd140f3669c6 Mon Sep 17 00:00:00 2001 From: Erica Z Date: Tue, 5 Nov 2024 10:01:07 +0100 Subject: [PATCH] fun with properties --- resources/playbar.blp | 18 +++++----- resources/window.blp | 7 ++-- src/ui/play_queue/song.rs | 6 ++-- src/ui/playbar.rs | 25 +++++--------- src/ui/window.rs | 69 ++++++++++++++++++++++++++++++++++----- 5 files changed, 86 insertions(+), 39 deletions(-) diff --git a/resources/playbar.blp b/resources/playbar.blp index ee021c5..93874da 100644 --- a/resources/playbar.blp +++ b/resources/playbar.blp @@ -36,7 +36,7 @@ template $AudreyUiPlaybar: Adw.Bin { xalign: 0; halign: start; - label: bind $song_title(template.song) as ; + label: bind template.song as <$AudreyPlaybinSong>.title; ellipsize: end; } @@ -46,7 +46,7 @@ template $AudreyUiPlaybar: Adw.Bin { ] xalign: 0; - label: bind $song_artist(template.song) as ; + label: bind template.song as <$AudreyPlaybinSong>.artist; ellipsize: end; } @@ -56,7 +56,7 @@ template $AudreyUiPlaybar: Adw.Bin { ] xalign: 0; - label: bind $song_album(template.song) as ; + label: bind template.song as <$AudreyPlaybinSong>.album; ellipsize: end; } } @@ -83,7 +83,7 @@ template $AudreyUiPlaybar: Adw.Bin { name: "seek-scale"; orientation: horizontal; width-request: 400; - // sensitive: bind $playbin_active (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>) as ; + sensitive: bind template.idle-active inverted; adjustment: Adjustment { lower: 0; value: bind template.position; @@ -111,35 +111,35 @@ template $AudreyUiPlaybar: Adw.Bin { Button { icon-name: "media-skip-backward"; valign: center; - // sensitive: bind $playbin_active (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>) as ; + sensitive: bind template.idle-active inverted; clicked => $on_skip_backward_clicked() swapped; } Button { icon-name: "media-seek-backward"; valign: center; - // sensitive: bind $playbin_active (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>) as ; + sensitive: bind template.idle-active inverted; clicked => $seek_backward() swapped; } Button { icon-name: bind $play_pause_icon_name(template.idle-active, template.pause) as ; valign: center; - // sensitive: bind $can_press_play (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>, template.playbin as <$AudreyPlaybin>.play-queue-length) as ; + sensitive: bind $play_pause_sensitive(template.playlist-count) as ; clicked => $on_play_pause_clicked() swapped; } Button { icon-name: "media-seek-forward"; valign: center; - // sensitive: bind $playbin_active (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>) as ; + sensitive: bind template.idle-active inverted; clicked => $seek_forward() swapped; } Button { icon-name: "media-skip-forward"; valign: center; - // sensitive: bind $playbin_active (template.playbin as <$AudreyPlaybin>.state as <$AudreyPlaybinState>) as ; + sensitive: bind template.idle-active inverted; clicked => $on_skip_forward_clicked() swapped; } } diff --git a/resources/window.blp b/resources/window.blp index df4f5cb..f1f519f 100644 --- a/resources/window.blp +++ b/resources/window.blp @@ -141,14 +141,15 @@ template $AudreyUiWindow: Adw.ApplicationWindow { [bottom] $AudreyUiPlaybar playbar { song: bind template.song; - playing_cover_art: bind template.playing_cover_art; - show_cover_art: bind $show_playbar_cover_art(stack.visible-child-name) as ; + playing-cover-art: bind template.playing-cover-art; + show-cover-art: bind $show_playbar_cover_art(stack.visible-child-name) as ; volume: bind template.volume bidirectional; mute: bind template.mute bidirectional; pause: bind template.pause bidirectional; position: bind template.time-pos; - duration: bind template.song as <$AudreyPlaybinSong>.duration; + duration: bind template.duration; idle-active: bind template.idle-active; + playlist-count: bind template.playlist-count; } } } diff --git a/src/ui/play_queue/song.rs b/src/ui/play_queue/song.rs index 46d4c69..113bdf0 100644 --- a/src/ui/play_queue/song.rs +++ b/src/ui/play_queue/song.rs @@ -8,7 +8,7 @@ mod imp { #[template(resource = "/eu/callcc/audrey/play_queue_song.ui")] #[properties(wrapper_type = super::Song)] pub struct Song { - #[property(type = i64, set = Self::set_playlist_pos)] + #[property(type = i32, set = Self::set_playlist_pos)] _playlist_pos: (), #[property(set, get)] @@ -163,9 +163,9 @@ mod imp { false } - fn set_playlist_pos(&self, playlist_pos: i64) { + fn set_playlist_pos(&self, playlist_pos: i32) { self.obj() - .set_current(playlist_pos == self.position.get() as i64); + .set_current(playlist_pos == self.position.get() as i32); } } } diff --git a/src/ui/playbar.rs b/src/ui/playbar.rs index 66910f6..71b6eb9 100644 --- a/src/ui/playbar.rs +++ b/src/ui/playbar.rs @@ -18,14 +18,17 @@ mod imp { #[property(get, set, default = true)] show_cover_art: Cell, + // synced with root window #[property(get, set)] - _volume: Cell, + _volume: Cell, #[property(get, set)] _mute: Cell, #[property(get, set)] _pause: Cell, #[property(get, set)] _idle_active: Cell, + #[property(get, set)] + _playlist_count: Cell, #[property(get, set)] position: Cell, @@ -58,21 +61,6 @@ mod imp { #[gtk::template_callbacks] impl Playbar { - #[template_callback] - fn song_title(&self, song: Option<&PlaybinSong>) -> Option { - song.map(|song| song.title()) - } - - #[template_callback] - fn song_artist(&self, song: Option<&PlaybinSong>) -> Option { - song.map(|song| song.artist()) - } - - #[template_callback] - fn song_album(&self, song: Option<&PlaybinSong>) -> Option { - song.map(|song| song.album()) - } - #[template_callback] fn format_timestamp(&self, s: f64) -> String { format!("{:02}:{:02}", (s as i64) / 64, (s as i64) % 60) @@ -164,6 +152,11 @@ mod imp { } } + #[template_callback] + fn play_pause_sensitive(&self, playlist_count: u32) -> bool { + playlist_count > 0 + } + fn window(&self) -> crate::ui::Window { self.obj().root().unwrap().dynamic_cast().unwrap() } diff --git a/src/ui/window.rs b/src/ui/window.rs index e89e8f7..959d691 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -36,18 +36,22 @@ mod imp { #[property(get)] playlist_model: gio::ListStore, - #[property(type = i64, get = Self::volume, set = Self::set_volume)] + #[property(type = u32, get = Self::volume, set = Self::set_volume)] _volume: (), #[property(type = bool, get = Self::mute, set = Self::set_mute)] _mute: (), #[property(type = bool, get = Self::pause, set = Self::set_pause)] _pause: (), - #[property(type = i64, get = Self::playlist_pos)] + #[property(type = i32, get = Self::playlist_pos)] _playlist_pos: (), #[property(type = f64, get = Self::time_pos)] _time_pos: (), + #[property(type = f64, get = Self::duration)] + _duration: (), // as reported by mpv, compare with song.duration #[property(type = bool, get = Self::idle_active)] _idle_active: (), + #[property(type = u32, get = Self::playlist_count)] + _playlist_count: (), } impl Default for Window { @@ -65,6 +69,8 @@ mod imp { mpv.observe_property(3, "playlist-pos").unwrap(); mpv.observe_property(4, "idle-active").unwrap(); mpv.observe_property(5, "time-pos").unwrap(); + mpv.observe_property(6, "playlist-count").unwrap(); + mpv.observe_property(7, "duration").unwrap(); // "Useful to drain property changes before a new file is loaded." mpv.add_hook(0, "on_before_start_file", 0).unwrap(); @@ -85,7 +91,9 @@ mod imp { _pause: (), _playlist_pos: (), _time_pos: (), + _duration: (), _idle_active: (), + _playlist_count: (), } } } @@ -153,6 +161,16 @@ mod imp { window.notify("time-pos"); } + 6 => { + assert_eq!(event.name, "playlist-count"); + window.notify("playlist-count"); + } + + 7 => { + assert_eq!(event.name, "duration"); + window.notify("duration"); + } + _ => unreachable!(), }, @@ -296,12 +314,16 @@ mod imp { self.setup.present(Some(self.obj().as_ref())); } - fn volume(&self) -> i64 { - self.mpv.get_property("volume").unwrap() + fn volume(&self) -> u32 { + self.mpv + .get_property::("volume") + .unwrap() + .try_into() + .unwrap() } - fn set_volume(&self, volume: i64) { - self.mpv.set_property("volume", volume).unwrap(); + fn set_volume(&self, volume: u32) { + self.mpv.set_property("volume", volume as i64).unwrap(); } fn mute(&self) -> bool { @@ -320,8 +342,12 @@ mod imp { self.mpv.set_property("pause", pause).unwrap(); } - fn playlist_pos(&self) -> i64 { - self.mpv.get_property("playlist-pos").unwrap() + fn playlist_pos(&self) -> i32 { + self.mpv + .get_property::("playlist-pos") + .unwrap() + .try_into() + .unwrap() } fn time_pos(&self) -> f64 { @@ -333,10 +359,37 @@ mod imp { .unwrap() } + fn duration(&self) -> f64 { + let duration = match self.mpv.get_property::("duration") { + Ok(duration) => Ok(Some(duration)), + Err(err) if err.is_property_unavailable() => { + Ok(self.song().as_ref().map(|song| song.duration() as f64)) + } + Err(err) => Err(err), + } + .unwrap(); + + assert_eq!( + duration.map(|f| f as i64), + self.song().as_ref().map(crate::PlaybinSong::duration), + "mpv duration doesn not match subsonic duration (this should probably be a warn)" + ); + + duration.unwrap_or(0.0) // placeholder + } + fn idle_active(&self) -> bool { self.mpv.get_property("idle-active").unwrap() } + fn playlist_count(&self) -> u32 { + self.mpv + .get_property::("playlist-count") + .unwrap() + .try_into() + .unwrap() + } + fn song(&self) -> Option { if self.obj().playlist_pos() < 0 { None