don't let that reference hang
This commit is contained in:
parent
ad51d16a06
commit
b966bc18df
2 changed files with 21 additions and 11 deletions
|
@ -36,15 +36,16 @@ mod imp {
|
||||||
self.mpv.set_property("gapless-audio", true).unwrap();
|
self.mpv.set_property("gapless-audio", true).unwrap();
|
||||||
// TODO: observe properties
|
// TODO: observe properties
|
||||||
|
|
||||||
glib::spawn_future_local(glib::clone!(
|
let self_weak = self.obj().downgrade();
|
||||||
#[weak(rename_to = app)]
|
glib::spawn_future_local(async move {
|
||||||
self,
|
while let Some(app) = self_weak.upgrade() {
|
||||||
async move {
|
// this song and dance is required so the strong reference to app
|
||||||
loop {
|
// isn't uselessly preserved during the await
|
||||||
app.mpv.tick().await;
|
let future = app.imp().mpv.tick();
|
||||||
}
|
drop(app);
|
||||||
|
future.await;
|
||||||
}
|
}
|
||||||
));
|
});
|
||||||
|
|
||||||
glib::spawn_future_local(async move {
|
glib::spawn_future_local(async move {
|
||||||
let conn = zbus::connection::Builder::session()
|
let conn = zbus::connection::Builder::session()
|
||||||
|
|
15
src/mpv.rs
15
src/mpv.rs
|
@ -45,12 +45,14 @@ impl fmt::Debug for Error {
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
use event_listener::{Event, IntoNotification};
|
use event_listener::{Event, IntoNotification};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
inner: NonNull<ffi::mpv_handle>,
|
inner: NonNull<ffi::mpv_handle>,
|
||||||
wakeup: Pin<Box<Event>>, // the wakeup callback holds a pointer to this
|
wakeup: Pin<Box<Event>>, // the wakeup callback holds a pointer to this
|
||||||
|
wait_event_cell: RefCell<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// The client API is generally fully thread-safe, unless otherwise noted.
|
// The client API is generally fully thread-safe, unless otherwise noted.
|
||||||
|
@ -89,7 +91,11 @@ impl Handle {
|
||||||
Error::from_return_code(unsafe { ffi::mpv_initialize(inner.as_ptr()) })
|
Error::from_return_code(unsafe { ffi::mpv_initialize(inner.as_ptr()) })
|
||||||
.expect("could not initialize mpv handle");
|
.expect("could not initialize mpv handle");
|
||||||
|
|
||||||
Self { inner, wakeup }
|
Self {
|
||||||
|
inner,
|
||||||
|
wakeup,
|
||||||
|
wait_event_cell: RefCell::new(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_property(&self, name: &str, value: impl FormatValue) -> Result<(), Error> {
|
pub fn set_property(&self, name: &str, value: impl FormatValue) -> Result<(), Error> {
|
||||||
|
@ -104,7 +110,9 @@ impl Handle {
|
||||||
|
|
||||||
fn drain_event_queue(&self) {
|
fn drain_event_queue(&self) {
|
||||||
loop {
|
loop {
|
||||||
|
let borrowed = self.wait_event_cell.borrow_mut();
|
||||||
let event = unsafe { &*ffi::mpv_wait_event(self.inner.as_ptr(), 0.0) };
|
let event = unsafe { &*ffi::mpv_wait_event(self.inner.as_ptr(), 0.0) };
|
||||||
|
|
||||||
match event.event_id {
|
match event.event_id {
|
||||||
ffi::mpv_event_id_MPV_EVENT_NONE => break,
|
ffi::mpv_event_id_MPV_EVENT_NONE => break,
|
||||||
|
|
||||||
|
@ -112,14 +120,15 @@ impl Handle {
|
||||||
|
|
||||||
_ => todo!("event {}", event.event_id),
|
_ => todo!("event {}", event.event_id),
|
||||||
}
|
}
|
||||||
|
drop(borrowed); // make sure the borrow is held until here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn tick(&self) {
|
pub fn tick(&self) -> impl std::future::Future<Output = ()> {
|
||||||
// take listener before we drain the event queue, so we don't miss any notifications
|
// take listener before we drain the event queue, so we don't miss any notifications
|
||||||
let listener = self.wakeup.listen();
|
let listener = self.wakeup.listen();
|
||||||
self.drain_event_queue();
|
self.drain_event_queue();
|
||||||
listener.await;
|
listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue