sure
This commit is contained in:
parent
8ab1e1e1fa
commit
859e1ca527
4 changed files with 38 additions and 20 deletions
|
@ -2,10 +2,11 @@ mod imp {
|
||||||
use crate::{mpv, ui};
|
use crate::{mpv, ui};
|
||||||
use adw::{prelude::*, subclass::prelude::*};
|
use adw::{prelude::*, subclass::prelude::*};
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
mpv: mpv::Handle,
|
mpv: Rc<mpv::Handle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
@ -36,14 +37,13 @@ mod imp {
|
||||||
self.mpv.set_property("gapless-audio", true).unwrap();
|
self.mpv.set_property("gapless-audio", true).unwrap();
|
||||||
// TODO: observe properties
|
// TODO: observe properties
|
||||||
|
|
||||||
let self_weak = self.obj().downgrade();
|
let mpv_weak = Rc::downgrade(&self.mpv);
|
||||||
glib::spawn_future_local(async move {
|
glib::spawn_future_local(async move {
|
||||||
while let Some(app) = self_weak.upgrade() {
|
while let Some(mpv) = mpv_weak.upgrade() {
|
||||||
// this song and dance is required so the strong reference to app
|
match mpv.tick() {
|
||||||
// isn't uselessly preserved during the await
|
None => break,
|
||||||
let future = app.imp().mpv.tick();
|
Some(listener) => listener.await,
|
||||||
drop(app);
|
}
|
||||||
future.await;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ pub use playbin::Playbin;
|
||||||
pub mod subsonic;
|
pub mod subsonic;
|
||||||
pub mod subsonic_vala;
|
pub mod subsonic_vala;
|
||||||
|
|
||||||
|
mod playbin2;
|
||||||
|
|
||||||
use gettextrs::{bind_textdomain_codeset, bindtextdomain, setlocale, textdomain, LocaleCategory};
|
use gettextrs::{bind_textdomain_codeset, bindtextdomain, setlocale, textdomain, LocaleCategory};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{gio, glib};
|
use gtk::{gio, glib};
|
||||||
|
|
39
src/mpv.rs
39
src/mpv.rs
|
@ -44,7 +44,7 @@ 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, EventListener, IntoNotification};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
@ -87,7 +87,10 @@ impl Handle {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up verbose logging for now
|
// 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
|
// 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."
|
// 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 {
|
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 {
|
||||||
|
@ -126,26 +136,31 @@ impl Handle {
|
||||||
let level = unsafe { CStr::from_ptr(data.level) }.to_str().unwrap();
|
let level = unsafe { CStr::from_ptr(data.level) }.to_str().unwrap();
|
||||||
let text = unsafe { CStr::from_ptr(data.text) }.to_str().unwrap();
|
let text = unsafe { CStr::from_ptr(data.text) }.to_str().unwrap();
|
||||||
print!("[{prefix}] {level}: {text}");
|
print!("[{prefix}] {level}: {text}");
|
||||||
},
|
}
|
||||||
|
|
||||||
11 => { /* deprecated, ignore */ }
|
11 => { /* deprecated, ignore */ }
|
||||||
|
|
||||||
_ => todo!("event {}", event.event_id),
|
_ => todo!("event {}", event.event_id),
|
||||||
}
|
}
|
||||||
drop(borrowed); // make sure the borrow is held until here
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tick(&self) -> impl std::future::Future<Output = ()> {
|
drop(borrowed); // make sure the borrow is held until here
|
||||||
// take listener before we drain the event queue, so we don't miss any notifications
|
Some(listener)
|
||||||
let listener = self.wakeup.listen();
|
|
||||||
self.drain_event_queue();
|
|
||||||
listener
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Handle {
|
impl Drop for Handle {
|
||||||
fn drop(&mut self) {
|
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 {
|
unsafe {
|
||||||
ffi::mpv_destroy(self.inner.as_ptr());
|
ffi::mpv_destroy(self.inner.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
1
src/playbin2.rs
Normal file
1
src/playbin2.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod imp {}
|
Loading…
Reference in a new issue