diff --git a/src/application.rs b/src/application.rs index 09cd415..28961df 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,14 +1,10 @@ mod imp { - use crate::{mpv, ui}; + use crate::ui; use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; - use std::rc::Rc; #[derive(Default)] - pub struct Application { - // FIXME: move somewhere else - mpv: Rc, - } + pub struct Application {} #[glib::object_subclass] impl ObjectSubclass for Application { @@ -26,64 +22,6 @@ mod imp { None => { let window = ui::Window::new(self.obj().as_ref()); window.present(); - - self.mpv - .set_property("audio-client-name", "audrey") - .unwrap(); - self.mpv - .set_property("user-agent", crate::USER_AGENT) - .unwrap(); - self.mpv.set_property("video", false).unwrap(); - self.mpv.set_property("prefetch-playlist", true).unwrap(); - self.mpv.set_property("gapless-audio", true).unwrap(); - // TODO: observe properties - - let mpv_weak = Rc::downgrade(&self.mpv); - glib::spawn_future_local(async move { - while let Some(mpv) = mpv_weak.upgrade() { - match mpv.tick() { - None => break, - Some(listener) => { - drop(mpv); // don't - listener.await; - } - } - } - }); - - glib::spawn_future_local(async move { - let conn = zbus::connection::Builder::session() - .expect("could not connect to the session bus") - .internal_executor(false) - .build() - .await - .expect("could not build connection to the session bus"); - - // run this in glib's main loop - glib::spawn_future_local(glib::clone!( - #[strong] - conn, - async move { - loop { - conn.executor().tick().await; - } - } - )); - - crate::Mpris::setup(conn.object_server(), &window) - .await - .expect("could not serve mpris"); - crate::mpris::Player::setup(conn.object_server(), &window.playbin()) - .await - .expect("could not serve mpris player"); - - drop(window); // don't keep this alive - - // always set up handlers before requesting service name - conn.request_name("org.mpris.MediaPlayer2.audrey") - .await - .expect("could not register name in session bus"); - }); } Some(win) => win.present(), } @@ -99,7 +37,6 @@ mod imp { impl Drop for Application { fn drop(&mut self) { println!("dropping AudreyApplication"); - self.mpv.command(["quit"]).unwrap(); } } } diff --git a/src/mpv/node.rs b/src/mpv/node.rs new file mode 100644 index 0000000..22c407e --- /dev/null +++ b/src/mpv/node.rs @@ -0,0 +1,7 @@ +use super::ffi; +use std::marker::PhantomData; + +pub struct Node<'a> { + pub(crate) ffi::mpv_node, + _ref: PhantomData<&'a ()>, +} diff --git a/src/ui/window.rs b/src/ui/window.rs index 9665941..b91b223 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -1,9 +1,11 @@ mod imp { + use crate::mpv; use adw::prelude::*; use adw::subclass::prelude::*; use glib::subclass::InitializingObject; use gtk::{gdk, glib}; use std::cell::{Cell, RefCell}; + use std::rc::Rc; #[derive(gtk::CompositeTemplate, glib::Properties, Default)] #[template(resource = "/eu/callcc/audrey/window.ui")] @@ -26,6 +28,7 @@ mod imp { pub(super) setup: crate::ui::Setup, pub(super) api: RefCell>, + pub(super) mpv: Rc, } #[glib::object_subclass] @@ -45,7 +48,72 @@ mod imp { } #[glib::derived_properties] - impl ObjectImpl for Window {} + impl ObjectImpl for Window { + fn constructed(&self) { + self.parent_constructed(); + + // set up mpv + self.mpv + .set_property("audio-client-name", "audrey") + .unwrap(); + self.mpv + .set_property("user-agent", crate::USER_AGENT) + .unwrap(); + self.mpv.set_property("video", false).unwrap(); + self.mpv.set_property("prefetch-playlist", true).unwrap(); + self.mpv.set_property("gapless-audio", true).unwrap(); + // TODO: observe properties + + let mpv_weak = Rc::downgrade(&self.mpv); + glib::spawn_future_local(async move { + while let Some(mpv) = mpv_weak.upgrade() { + match mpv.tick() { + None => break, + Some(listener) => { + drop(mpv); // don't + listener.await; + } + } + } + }); + + // set up mpris + let window = self.obj().clone(); + glib::spawn_future_local(async move { + let conn = zbus::connection::Builder::session() + .expect("could not connect to the session bus") + .internal_executor(false) + .build() + .await + .expect("could not build connection to the session bus"); + + // run this in glib's main loop + glib::spawn_future_local(glib::clone!( + #[strong] + conn, + async move { + loop { + conn.executor().tick().await; + } + } + )); + + crate::Mpris::setup(conn.object_server(), &window) + .await + .expect("could not serve mpris"); + crate::mpris::Player::setup(conn.object_server(), &window.playbin()) + .await + .expect("could not serve mpris player"); + + drop(window); // don't keep this alive + + // always set up handlers before requesting service name + conn.request_name("org.mpris.MediaPlayer2.audrey") + .await + .expect("could not register name in session bus"); + }); + } + } impl WidgetImpl for Window {} @@ -116,6 +184,13 @@ mod imp { todo!() } } + + impl Drop for Window { + fn drop(&mut self) { + println!("dropping AudreyUiWindow"); + self.mpv.command(["quit"]).unwrap(); + } + } } use adw::prelude::*;