This commit is contained in:
Erica Z 2024-11-02 20:57:12 +01:00
parent 8ab1e1e1fa
commit 859e1ca527
4 changed files with 38 additions and 20 deletions

View file

@ -2,10 +2,11 @@ mod imp {
use crate::{mpv, ui};
use adw::{prelude::*, subclass::prelude::*};
use gtk::glib;
use std::rc::Rc;
#[derive(Default)]
pub struct Application {
mpv: mpv::Handle,
mpv: Rc<mpv::Handle>,
}
#[glib::object_subclass]
@ -36,14 +37,13 @@ mod imp {
self.mpv.set_property("gapless-audio", true).unwrap();
// TODO: observe properties
let self_weak = self.obj().downgrade();
let mpv_weak = Rc::downgrade(&self.mpv);
glib::spawn_future_local(async move {
while let Some(app) = self_weak.upgrade() {
// this song and dance is required so the strong reference to app
// isn't uselessly preserved during the await
let future = app.imp().mpv.tick();
drop(app);
future.await;
while let Some(mpv) = mpv_weak.upgrade() {
match mpv.tick() {
None => break,
Some(listener) => listener.await,
}
}
});

View file

@ -17,6 +17,8 @@ pub use playbin::Playbin;
pub mod subsonic;
pub mod subsonic_vala;
mod playbin2;
use gettextrs::{bind_textdomain_codeset, bindtextdomain, setlocale, textdomain, LocaleCategory};
use gtk::prelude::*;
use gtk::{gio, glib};

View file

@ -44,7 +44,7 @@ impl fmt::Debug for Error {
impl std::error::Error for Error {}
use event_listener::{Event, IntoNotification};
use event_listener::{Event, EventListener, IntoNotification};
use std::cell::RefCell;
use std::pin::Pin;
use std::ptr::NonNull;
@ -87,7 +87,10 @@ impl Handle {
}
// set up verbose logging for now
Error::from_return_code(unsafe { ffi::mpv_request_log_messages(inner.as_ptr(), c"v".as_ptr()) }).unwrap();
Error::from_return_code(unsafe {
ffi::mpv_request_log_messages(inner.as_ptr(), c"v".as_ptr())
})
.unwrap();
// 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."
@ -111,9 +114,16 @@ impl Handle {
})
}
fn drain_event_queue(&self) {
// TODO: return None on SHUTDOWN possibly?
pub fn tick(&self) -> Option<EventListener> {
// take listener before we drain the event queue, so we don't miss any notifications
let listener = self.wakeup.listen();
let borrowed = self
.wait_event_cell
.try_borrow_mut()
.expect("Mpv::tick is not reentrant");
loop {
let borrowed = self.wait_event_cell.borrow_mut();
let event = unsafe { &*ffi::mpv_wait_event(self.inner.as_ptr(), 0.0) };
match event.event_id {
@ -126,26 +136,31 @@ impl Handle {
let level = unsafe { CStr::from_ptr(data.level) }.to_str().unwrap();
let text = unsafe { CStr::from_ptr(data.text) }.to_str().unwrap();
print!("[{prefix}] {level}: {text}");
},
}
11 => { /* deprecated, ignore */ }
_ => todo!("event {}", event.event_id),
}
drop(borrowed); // make sure the borrow is held until here
}
}
pub fn tick(&self) -> impl std::future::Future<Output = ()> {
// take listener before we drain the event queue, so we don't miss any notifications
let listener = self.wakeup.listen();
self.drain_event_queue();
listener
drop(borrowed); // make sure the borrow is held until here
Some(listener)
}
}
impl Drop for Handle {
fn drop(&mut self) {
// let any executor ticking tasks know we're ded
self.wakeup.notify(u32::MAX.relaxed());
// just in case
unsafe {
ffi::mpv_wait_async_requests(self.inner.as_ptr());
}
// drain event queue (we're &mut so we know we have exclusive access)
self.tick();
unsafe {
ffi::mpv_destroy(self.inner.as_ptr());
}

1
src/playbin2.rs Normal file
View file

@ -0,0 +1 @@
mod imp {}