From e4083288e674fb0fc4b6bb9ca3bfd3cc1c167d96 Mon Sep 17 00:00:00 2001 From: Erica Z Date: Sun, 3 Nov 2024 15:06:11 +0100 Subject: [PATCH] now safer --- src/mpv/handle.rs | 17 +++++++++++++++++ src/playbin2.rs | 4 +--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/mpv/handle.rs b/src/mpv/handle.rs index 92e9d42..4407443 100644 --- a/src/mpv/handle.rs +++ b/src/mpv/handle.rs @@ -13,6 +13,8 @@ pub struct Handle { inner: NonNull, wakeup: Pin>, // the wakeup callback holds a pointer to this wait_event_cell: RefCell<()>, + + pending_hooks: RefCell>, } // The client API is generally fully thread-safe, unless otherwise noted. @@ -67,6 +69,8 @@ impl Handle { inner, wakeup, wait_event_cell: RefCell::new(()), + + pending_hooks: RefCell::new(vec![]), } } @@ -141,6 +145,18 @@ impl Handle { Error::from_return_code(unsafe { ffi::mpv_hook_continue(self.inner.as_ptr(), id) }) } + pub fn continue_hook(&self, id: u64) -> Result<(), Error> { + let mut pending_hooks = self.pending_hooks.borrow_mut(); + for (i, pending_id) in pending_hooks.iter().enumerate() { + if *pending_id == id { + pending_hooks.swap_remove(i); + return unsafe { self.continue_hook_unchecked(id) }; + } + } + + panic!("invalid hook id") + } + // should take listener before we drain the event queue, so we don't miss any notifications pub fn wakeup_listener(&self) -> EventListener { self.wakeup.listen() @@ -219,6 +235,7 @@ impl Handle { ffi::mpv_event_id_MPV_EVENT_HOOK => { let data = unsafe { &*(event.data as *mut ffi::mpv_event_hook) }; + self.pending_hooks.borrow_mut().push(data.id); Some(MpvEvent::Hook(HookEvent { reply_userdata: event.reply_userdata, name: unsafe { CStr::from_ptr(data.name) } diff --git a/src/playbin2.rs b/src/playbin2.rs index e149d96..ede297c 100644 --- a/src/playbin2.rs +++ b/src/playbin2.rs @@ -179,9 +179,7 @@ where assert_eq!(&event.name, "on_before_start_file"); // just use this as a barrier println!("on_before_start_file triggered"); - unsafe { - self.mpv.continue_hook_unchecked(event.id).unwrap(); - } + self.mpv.continue_hook(event.id).unwrap(); } _ => unreachable!(),