mod imp { use adw::prelude::*; use adw::subclass::prelude::*; use glib::subclass::InitializingObject; use gtk::{gdk, glib}; use std::cell::{Cell, RefCell}; #[derive(glib::Properties, gtk::CompositeTemplate, Default)] #[properties(wrapper_type = super::Playbar)] #[template(resource = "/eu/callcc/audrey/playbar.ui")] pub struct Playbar { #[property(get, set)] song: RefCell>, #[property(get, set)] playing_cover_art: RefCell>, #[property(get, set)] playbin: RefCell>, // TODO: weak #[property(get, set, default = true)] show_cover_art: Cell, #[property(get = Self::get_volume, set = Self::set_volume)] _volume: i32, } #[glib::object_subclass] impl ObjectSubclass for Playbar { const NAME: &'static str = "AudreyUiPlaybar"; type Type = super::Playbar; type ParentType = adw::Bin; fn class_init(klass: &mut Self::Class) { klass.bind_template(); klass.bind_template_callbacks(); } fn instance_init(obj: &InitializingObject) { obj.init_template(); } } #[glib::derived_properties] impl ObjectImpl for Playbar {} impl WidgetImpl for Playbar {} impl BinImpl for Playbar {} #[gtk::template_callbacks] impl Playbar { #[template_callback] fn song_title(&self, song: Option<&crate::playbin::Song>) -> String { match song { None => "".to_owned(), Some(song) => song.get_title().to_string(), } } #[template_callback] fn song_artist(&self, song: Option<&crate::playbin::Song>) -> String { match song { None => "".to_owned(), Some(song) => song.get_artist().to_string(), } } #[template_callback] fn song_album(&self, song: Option<&crate::playbin::Song>) -> String { match song { None => "".to_owned(), Some(song) => song.get_album().to_string(), } } #[template_callback] fn format_timestamp(&self, s: f64) -> String { format!("{:02}:{:02}", (s as i64) / 64, (s as i64) % 60) } #[template_callback] fn playbin_active(&self, state: crate::playbin::State) -> bool { state != crate::playbin::State::Stopped } #[template_callback] fn can_press_play(&self, state: crate::playbin::State, n_items: u32) -> bool { !(state == crate::playbin::State::Stopped && n_items == 0) } #[template_callback] fn play_pause_icon_name(&self, state: crate::playbin::State) -> &'static str { match state { crate::playbin::State::Playing => "media-playback-pause", _ => "media-playback-start", } } #[template_callback] fn mute_button_icon_name(&self, mute: bool) -> &'static str { if mute { "audio-volume-muted" } else { "audio-volume-high" } } #[template_callback] fn on_play_position_seek( &self, _scroll_type: gtk::ScrollType, value: f64, range: >k::Range, ) -> bool { let playbin = self.playbin.borrow(); let playbin = playbin.as_ref().unwrap(); if range.adjustment().lower() < range.adjustment().upper() { playbin.seek(value); } false } #[template_callback] fn on_skip_forward_clicked(&self) { // this.playbin.go_to_next_track (); todo!() } #[template_callback] fn on_skip_backward_clicked(&self) { // this.playbin.go_to_prev_track (); todo!() } #[template_callback] fn seek_backward(&self) { // 10 seconds // double new_position = playbin.position - 10.0; // if (new_position < 0.0) new_position = 0.0; // this.playbin.seek (new_position); todo!() } #[template_callback] fn seek_forward(&self) { // 10 seconds // double new_position = playbin.position + 10.0; // if (new_position > this.playbin.duration) new_position = this.playbin.duration; // this.playbin.seek (new_position); todo!() } #[template_callback] fn on_play_pause_clicked(&self, _button: >k::Button) { let playbin = self.playbin.borrow(); let playbin = playbin.as_ref().unwrap(); if playbin.get_state() == crate::playbin::State::Playing { playbin.pause(); } else { playbin.play(); } } #[template_callback] fn on_mute_toggle(&self) { //this.playbin.mute = !this.playbin.mute; todo!() } fn get_volume(&self) -> i32 { let playbin = self.playbin.borrow(); match playbin.as_ref() { None => 100, Some(playbin) => playbin.get_volume(), } } fn set_volume(&self, value: i32) { let playbin = self.playbin.borrow(); let playbin = playbin.as_ref().unwrap(); playbin.set_volume(value); } } } use gtk::glib; glib::wrapper! { pub struct Playbar(ObjectSubclass) @extends adw::Bin, gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget; } mod ffi { use glib::translate::IntoGlib; use gtk::glib; use gtk::prelude::*; #[no_mangle] pub extern "C" fn audrey_ui_playbar_get_type() -> glib::ffi::GType { super::Playbar::static_type().into_glib() } }