2024-11-02 11:24:25 +00:00
|
|
|
mod imp {
|
|
|
|
use adw::prelude::*;
|
|
|
|
use adw::subclass::prelude::*;
|
|
|
|
use glib::subclass::InitializingObject;
|
|
|
|
use gtk::{gdk, glib};
|
|
|
|
use std::cell::{Cell, RefCell};
|
2024-10-29 13:02:29 +00:00
|
|
|
|
2024-11-02 11:24:25 +00:00
|
|
|
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
|
|
|
|
#[template(resource = "/eu/callcc/audrey/window.ui")]
|
|
|
|
#[properties(wrapper_type = super::Window)]
|
|
|
|
pub struct Window {
|
|
|
|
#[template_child]
|
|
|
|
pub(super) playbar: TemplateChild<crate::ui::Playbar>,
|
|
|
|
|
|
|
|
#[property(get, set)]
|
|
|
|
playbin: RefCell<crate::Playbin>,
|
|
|
|
|
|
|
|
#[property(get, set, default = false)]
|
|
|
|
can_click_shuffle_all: Cell<bool>,
|
|
|
|
|
|
|
|
#[property(get, set, nullable)]
|
|
|
|
playing_cover_art: RefCell<Option<gdk::Paintable>>,
|
|
|
|
|
|
|
|
#[property(get, set, nullable)]
|
|
|
|
song: RefCell<Option<crate::playbin::Song>>,
|
|
|
|
|
|
|
|
pub(super) setup: crate::ui::Setup,
|
|
|
|
pub(super) api: RefCell<Option<crate::subsonic_vala::Client>>,
|
2024-10-29 13:02:29 +00:00
|
|
|
}
|
|
|
|
|
2024-11-02 11:24:25 +00:00
|
|
|
#[glib::object_subclass]
|
|
|
|
impl ObjectSubclass for Window {
|
|
|
|
const NAME: &'static str = "AudreyUiWindow";
|
|
|
|
type Type = super::Window;
|
|
|
|
type ParentType = adw::ApplicationWindow;
|
|
|
|
|
|
|
|
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-29 13:02:29 +00:00
|
|
|
}
|
|
|
|
|
2024-11-02 11:24:25 +00:00
|
|
|
#[glib::derived_properties]
|
|
|
|
impl ObjectImpl for Window {}
|
|
|
|
|
|
|
|
impl WidgetImpl for Window {}
|
|
|
|
|
|
|
|
impl WindowImpl for Window {}
|
|
|
|
|
|
|
|
impl ApplicationWindowImpl for Window {}
|
|
|
|
|
|
|
|
impl AdwApplicationWindowImpl for Window {}
|
|
|
|
|
|
|
|
#[gtk::template_callbacks]
|
|
|
|
impl Window {
|
|
|
|
#[template_callback]
|
|
|
|
fn show_playbar_cover_art(&self, stack_child: Option<&str>) -> bool {
|
|
|
|
stack_child != Some("play-queue")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[template_callback]
|
|
|
|
async fn shuffle_all(&self) {
|
|
|
|
/*
|
|
|
|
this.can_click_shuffle_all = false;
|
|
|
|
this.playbin.clear ();
|
|
|
|
api.get_random_songs.begin (null, (song) => {
|
|
|
|
this.playbin.append_track (song);
|
|
|
|
}, (obj, res) => {
|
|
|
|
try {
|
|
|
|
api.get_random_songs.end (res);
|
|
|
|
} catch (Error e) {
|
|
|
|
error ("could not get random songs: %s", e.message);
|
|
|
|
}
|
|
|
|
this.can_click_shuffle_all = true;
|
|
|
|
|
|
|
|
this.playbin.select_track (0);
|
|
|
|
});*/
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[template_callback]
|
|
|
|
fn show_setup_dialog(&self) {
|
|
|
|
self.setup.present(Some(self.obj().as_ref()));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn now_playing(&self, _song: &crate::playbin::Song) {
|
|
|
|
/*
|
|
|
|
this.song = song;
|
|
|
|
// api.scrobble.begin (this.song.id); TODO
|
|
|
|
|
|
|
|
if (this.cancel_loading_art != null) {
|
|
|
|
this.cancel_loading_art.cancel ();
|
|
|
|
}
|
|
|
|
this.cancel_loading_art = new GLib.Cancellable ();
|
|
|
|
|
|
|
|
this.playing_cover_art = null; // TODO: preload next art somehow
|
|
|
|
this.cover_art_loading = true;
|
|
|
|
|
|
|
|
string song_id = this.song.id;
|
|
|
|
this.api.cover_art.begin (song_id, -1, Priority.DEFAULT, this.cancel_loading_art, (obj, res) => {
|
|
|
|
try {
|
|
|
|
this.playing_cover_art = Gdk.Texture.for_pixbuf (this.api.cover_art.end (res));
|
|
|
|
this.cover_art_loading = false;
|
|
|
|
} catch (Error e) {
|
|
|
|
if (!(e is IOError.CANCELLED)) {
|
|
|
|
warning ("could not load cover for %s: %s", song_id, e.message);
|
|
|
|
this.cover_art_loading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
*/
|
|
|
|
todo!()
|
|
|
|
}
|
2024-10-29 13:02:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
use adw::prelude::*;
|
2024-11-02 11:24:25 +00:00
|
|
|
use adw::subclass::prelude::*;
|
|
|
|
use gtk::{gdk, gio, glib};
|
2024-10-29 13:02:29 +00:00
|
|
|
|
|
|
|
glib::wrapper! {
|
2024-11-02 11:24:25 +00:00
|
|
|
pub struct Window(ObjectSubclass<imp::Window>)
|
2024-10-29 13:02:29 +00:00
|
|
|
@extends adw::ApplicationWindow, gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
|
|
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Window {
|
|
|
|
pub fn new(app: &impl IsA<gtk::Application>) -> Self {
|
2024-11-02 11:24:25 +00:00
|
|
|
let window: Self = glib::Object::builder().property("application", app).build();
|
|
|
|
|
|
|
|
window
|
|
|
|
.playbin()
|
|
|
|
.bind_property("volume", &*window.imp().playbar, "volume")
|
|
|
|
.bidirectional()
|
|
|
|
.sync_create()
|
|
|
|
.build();
|
|
|
|
|
|
|
|
window.imp().setup.connect_closure(
|
|
|
|
"connected",
|
|
|
|
false,
|
|
|
|
glib::closure_local!(
|
|
|
|
#[weak]
|
|
|
|
window,
|
|
|
|
move |_setup: crate::ui::Setup, api: crate::subsonic_vala::Client| {
|
|
|
|
window.imp().api.replace(Some(api.clone()));
|
|
|
|
window.playbin().set_api(&api);
|
|
|
|
window.set_can_click_shuffle_all(true);
|
|
|
|
}
|
|
|
|
),
|
|
|
|
);
|
|
|
|
window.imp().setup.load();
|
|
|
|
|
|
|
|
window.playbin().connect_closure(
|
|
|
|
"new-track",
|
|
|
|
false,
|
|
|
|
glib::closure_local!(
|
|
|
|
#[weak]
|
|
|
|
window,
|
|
|
|
move |_playbin: crate::Playbin, song: crate::playbin::Song| {
|
|
|
|
window.imp().now_playing(&song);
|
|
|
|
}
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
window.playbin().connect_closure(
|
|
|
|
"stopped",
|
|
|
|
false,
|
|
|
|
glib::closure_local!(
|
|
|
|
#[weak]
|
|
|
|
window,
|
|
|
|
move |_playbin: crate::Playbin| {
|
|
|
|
window.set_playing_cover_art(None::<gdk::Paintable>);
|
|
|
|
window.set_song(None::<crate::playbin::Song>);
|
|
|
|
}
|
|
|
|
),
|
|
|
|
);
|
2024-11-01 12:50:29 +00:00
|
|
|
|
2024-11-02 11:24:25 +00:00
|
|
|
window
|
2024-11-01 12:50:29 +00:00
|
|
|
}
|
2024-10-29 13:02:29 +00:00
|
|
|
}
|