audrey/src/ui/playbar.rs

186 lines
5.5 KiB
Rust
Raw Normal View History

2024-10-30 11:45:50 +00:00
mod imp {
use adw::prelude::*;
use adw::subclass::prelude::*;
use glib::subclass::InitializingObject;
2024-11-01 16:31:54 +00:00
use glib::{gformat, GString, WeakRef};
2024-10-30 11:45:50 +00:00
use gtk::{gdk, glib};
use std::cell::{Cell, RefCell};
2024-10-30 10:42:03 +00:00
2024-10-30 11:45:50 +00:00
#[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<Option<crate::playbin::Song>>,
#[property(get, set)]
playing_cover_art: RefCell<Option<gdk::Paintable>>,
#[property(get, set)]
2024-11-01 16:31:54 +00:00
playbin: WeakRef<crate::Playbin>,
2024-10-30 11:45:50 +00:00
#[property(get, set, default = true)]
show_cover_art: Cell<bool>,
2024-10-31 06:59:09 +00:00
#[property(type = i32, get = Self::volume, set = Self::set_volume)]
_volume: (),
2024-10-30 10:42:03 +00:00
}
2024-10-30 11:45:50 +00:00
#[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<Self>) {
obj.init_template();
}
2024-10-30 10:42:03 +00:00
}
2024-10-30 11:45:50 +00:00
#[glib::derived_properties]
impl ObjectImpl for Playbar {}
impl WidgetImpl for Playbar {}
impl BinImpl for Playbar {}
#[gtk::template_callbacks]
impl Playbar {
#[template_callback]
2024-10-31 07:15:35 +00:00
fn song_title(&self, song: Option<&crate::playbin::Song>) -> Option<GString> {
song.map(|song| song.title())
2024-10-30 11:45:50 +00:00
}
#[template_callback]
2024-10-31 07:15:35 +00:00
fn song_artist(&self, song: Option<&crate::playbin::Song>) -> Option<GString> {
song.map(|song| song.artist())
2024-10-30 11:45:50 +00:00
}
#[template_callback]
2024-10-31 07:15:35 +00:00
fn song_album(&self, song: Option<&crate::playbin::Song>) -> Option<GString> {
song.map(|song| song.album())
2024-10-30 11:45:50 +00:00
}
#[template_callback]
2024-10-31 07:15:35 +00:00
fn format_timestamp(&self, s: f64) -> GString {
gformat!("{:02}:{:02}", (s as i64) / 64, (s as i64) % 60)
2024-10-30 11:45:50 +00:00
}
#[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 {
2024-10-30 11:59:16 +00:00
if mute {
"audio-volume-muted"
} else {
"audio-volume-high"
}
2024-10-30 11:45:50 +00:00
}
#[template_callback]
2024-10-30 11:59:16 +00:00
fn on_play_position_seek(
&self,
_scroll_type: gtk::ScrollType,
2024-10-30 12:25:27 +00:00
value: f64,
range: &gtk::Range,
2024-10-30 11:59:16 +00:00
) -> bool {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-30 12:25:27 +00:00
if range.adjustment().lower() < range.adjustment().upper() {
playbin.seek(value);
2024-10-30 11:45:50 +00:00
}
2024-10-30 12:25:27 +00:00
false
2024-10-30 11:45:50 +00:00
}
#[template_callback]
fn on_skip_forward_clicked(&self) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-31 06:59:09 +00:00
playbin.go_to_next_track();
2024-10-30 11:45:50 +00:00
}
#[template_callback]
fn on_skip_backward_clicked(&self) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-31 06:59:09 +00:00
playbin.go_to_prev_track();
2024-10-30 11:45:50 +00:00
}
#[template_callback]
fn seek_backward(&self) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-30 11:45:50 +00:00
// 10 seconds
2024-10-31 06:59:09 +00:00
let mut new_position = playbin.position() - 10.0;
if new_position < 0.0 {
new_position = 0.0;
}
playbin.seek(new_position);
2024-10-30 11:45:50 +00:00
}
#[template_callback]
fn seek_forward(&self) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-30 11:45:50 +00:00
// 10 seconds
2024-10-31 06:59:09 +00:00
let mut new_position = playbin.position() + 10.0;
if new_position > playbin.duration() {
new_position = playbin.duration();
}
playbin.seek(new_position);
2024-10-30 11:45:50 +00:00
}
2024-10-30 11:59:16 +00:00
2024-10-30 11:45:50 +00:00
#[template_callback]
2024-10-30 11:59:16 +00:00
fn on_play_pause_clicked(&self, _button: &gtk::Button) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-30 11:59:16 +00:00
2024-10-31 06:59:09 +00:00
if playbin.state() == crate::playbin::State::Playing {
2024-10-30 11:59:16 +00:00
playbin.pause();
} else {
playbin.play();
}
2024-10-30 11:45:50 +00:00
}
#[template_callback]
fn on_mute_toggle(&self) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-31 06:59:09 +00:00
playbin.set_mute(!playbin.mute());
2024-10-30 11:45:50 +00:00
}
2024-10-30 12:09:22 +00:00
2024-10-31 06:59:09 +00:00
fn volume(&self) -> i32 {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade();
2024-10-30 12:09:22 +00:00
2024-11-01 16:31:54 +00:00
match playbin {
2024-10-30 12:09:22 +00:00
None => 100,
2024-10-31 06:59:09 +00:00
Some(playbin) => playbin.volume(),
2024-10-30 12:09:22 +00:00
}
}
fn set_volume(&self, value: i32) {
2024-11-01 16:31:54 +00:00
let playbin = self.playbin.upgrade().unwrap();
2024-10-30 12:09:22 +00:00
playbin.set_volume(value);
}
2024-10-30 10:42:03 +00:00
}
}
use gtk::glib;
glib::wrapper! {
2024-10-30 11:45:50 +00:00
pub struct Playbar(ObjectSubclass<imp::Playbar>)
2024-10-30 10:42:03 +00:00
@extends adw::Bin, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
2024-10-30 11:45:50 +00:00
}