use event listener for mpv wakeup
This commit is contained in:
parent
f194e1a608
commit
2aee230606
2 changed files with 26 additions and 34 deletions
|
@ -27,7 +27,6 @@ mod imp {
|
||||||
window.present();
|
window.present();
|
||||||
|
|
||||||
let mut mpv = self.mpv.borrow_mut();
|
let mut mpv = self.mpv.borrow_mut();
|
||||||
mpv.initialize().expect("could not initialize mpv");
|
|
||||||
mpv.set_property("audio-client-name", "audrey").unwrap();
|
mpv.set_property("audio-client-name", "audrey").unwrap();
|
||||||
mpv.set_property("user-agent", crate::USER_AGENT).unwrap();
|
mpv.set_property("user-agent", crate::USER_AGENT).unwrap();
|
||||||
mpv.set_property("video", false).unwrap();
|
mpv.set_property("video", false).unwrap();
|
||||||
|
@ -44,8 +43,7 @@ mod imp {
|
||||||
self,
|
self,
|
||||||
async move {
|
async move {
|
||||||
loop {
|
loop {
|
||||||
app.mpv.borrow().wait().await;
|
app.mpv.borrow_mut().tick().await;
|
||||||
app.mpv.borrow_mut().tick();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
56
src/mpv.rs
56
src/mpv.rs
|
@ -46,11 +46,13 @@ impl std::error::Error for Error {}
|
||||||
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
use event_listener::{Event, IntoNotification};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
inner: NonNull<ffi::mpv_handle>,
|
inner: NonNull<ffi::mpv_handle>,
|
||||||
_wakeup_send: Pin<Box<async_channel::Sender<()>>>, // the wakeup callback controls this one
|
wakeup: Pin<Box<Event>>, // the wakeup callback holds a pointer to this
|
||||||
wakeup_recv: async_channel::Receiver<()>,
|
tick_cell: RefCell<()>,
|
||||||
|
|
||||||
observed_property_callbacks:
|
observed_property_callbacks:
|
||||||
Vec<Pin<Box<Box<dyn FnMut(ffi::mpv_format, *mut c_void) + 'static>>>>,
|
Vec<Pin<Box<Box<dyn FnMut(ffi::mpv_format, *mut c_void) + 'static>>>>,
|
||||||
|
@ -63,52 +65,43 @@ pub struct Handle {
|
||||||
|
|
||||||
impl Default for Handle {
|
impl Default for Handle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::create()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handle {
|
impl Handle {
|
||||||
pub fn create() -> Self {
|
pub fn new() -> Self {
|
||||||
let inner =
|
let inner =
|
||||||
NonNull::new(unsafe { ffi::mpv_create() }).expect("could not create mpv handle");
|
NonNull::new(unsafe { ffi::mpv_create() }).expect("could not create mpv handle");
|
||||||
|
|
||||||
let (wakeup_send, wakeup_recv) = async_channel::bounded(1);
|
let wakeup = Box::pin(Event::new());
|
||||||
let wakeup_send = Box::pin(wakeup_send);
|
|
||||||
|
|
||||||
extern "C" fn wakeup_callback(d: *mut c_void) {
|
extern "C" fn wakeup_callback(d: *mut c_void) {
|
||||||
let d = d as *const async_channel::Sender<()>;
|
let d = d as *const Event;
|
||||||
let wakeup_send = unsafe { &*d };
|
let wakeup = unsafe { &*d };
|
||||||
match wakeup_send.try_send(()) {
|
wakeup.notify(1_u32.relaxed()); // mpv has its own synchronization, trust it
|
||||||
Ok(()) => {}
|
|
||||||
Err(async_channel::TrySendError::Full(())) => {
|
|
||||||
// assume the main thread has already been notified
|
|
||||||
}
|
|
||||||
Err(async_channel::TrySendError::Closed(())) => {
|
|
||||||
panic!("wakeup channgel was closed before mpv handle was finalized");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::mpv_set_wakeup_callback(
|
ffi::mpv_set_wakeup_callback(
|
||||||
inner.as_ptr(),
|
inner.as_ptr(),
|
||||||
Some(wakeup_callback),
|
Some(wakeup_callback),
|
||||||
std::ptr::from_ref::<async_channel::Sender<()>>(&wakeup_send) as *mut c_void,
|
std::ptr::from_ref::<Event>(&wakeup) as *mut c_void,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: maybe we need to set something before initialization, but idk
|
||||||
|
// also wed need a builder, since "Note that you should avoid doing concurrent accesses on the uninitialized client handle."
|
||||||
|
Error::from_return_code(unsafe { ffi::mpv_initialize(inner.as_ptr()) }).expect("could not initialize mpv handle");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: inner,
|
inner: inner,
|
||||||
_wakeup_send: wakeup_send,
|
wakeup: wakeup,
|
||||||
wakeup_recv: wakeup_recv,
|
tick_cell: RefCell::new(()),
|
||||||
|
|
||||||
observed_property_callbacks: vec![],
|
observed_property_callbacks: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(&self) -> Result<(), Error> {
|
|
||||||
Error::from_return_code(unsafe { ffi::mpv_initialize(self.inner.as_ptr()) })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_property<'a>(&self, name: &str, value: impl FormatValue) -> Result<(), Error> {
|
pub fn set_property<'a>(&self, name: &str, value: impl FormatValue) -> Result<(), Error> {
|
||||||
// need to add zero terminator
|
// need to add zero terminator
|
||||||
let name = CString::new(name).expect("null bytes in property name");
|
let name = CString::new(name).expect("null bytes in property name");
|
||||||
|
@ -143,14 +136,13 @@ impl Handle {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait(&self) {
|
pub async fn tick(&self) {
|
||||||
match self.wakeup_recv.recv().await {
|
// mpv_wait_event is not reentrant!! use a refcell to ensure that
|
||||||
Ok(()) => {}
|
self.tick_cell.borrow_mut();
|
||||||
Err(async_channel::RecvError) => unreachable!(),
|
|
||||||
}
|
// take listener before we drain the event loop, so we don't miss any notifications
|
||||||
}
|
let listener = self.wakeup.listen();
|
||||||
|
|
||||||
pub fn tick(&mut self) {
|
|
||||||
loop {
|
loop {
|
||||||
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 {
|
||||||
|
@ -170,6 +162,8 @@ impl Handle {
|
||||||
_ => todo!("event {}", event.event_id),
|
_ => todo!("event {}", event.event_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listener.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue