many changes
This commit is contained in:
parent
dbd209f904
commit
225292d08a
6 changed files with 290 additions and 47 deletions
|
@ -4,7 +4,7 @@ mod error;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|
||||||
mod format;
|
mod format;
|
||||||
pub use format::SetProperty;
|
pub use format::{GetProperty, SetProperty};
|
||||||
|
|
||||||
mod handle;
|
mod handle;
|
||||||
pub use handle::Handle;
|
pub use handle::Handle;
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub enum Event {
|
||||||
PlaybackRestart,
|
PlaybackRestart,
|
||||||
PropertyChange(PropertyEvent),
|
PropertyChange(PropertyEvent),
|
||||||
//QueueOverflow,
|
//QueueOverflow,
|
||||||
//Hook,
|
Hook(HookEvent),
|
||||||
Unknown(u32),
|
Unknown(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,15 +55,12 @@ pub struct LogMessageEvent {
|
||||||
pub struct PropertyEvent {
|
pub struct PropertyEvent {
|
||||||
pub reply_userdata: u64,
|
pub reply_userdata: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: PropertyEventValue,
|
//pub value: PropertyEventValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum PropertyEventValue {
|
pub struct HookEvent {
|
||||||
None,
|
pub reply_userdata: u64,
|
||||||
String(String),
|
pub name: String,
|
||||||
OsdString(String),
|
pub id: u64,
|
||||||
Flag(bool),
|
|
||||||
Int64(i64),
|
|
||||||
Double(f64),
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +1,123 @@
|
||||||
use super::ffi;
|
use super::{ffi, Error};
|
||||||
use std::ffi::{c_char, c_int, c_void, CString};
|
use std::ffi::{c_char, c_int, c_void, CString};
|
||||||
|
|
||||||
pub trait SetProperty {
|
pub trait SetProperty {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// see mpv_set_property
|
/// see mpv_set_property
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int;
|
unsafe fn set_property(
|
||||||
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SetProperty for String {
|
impl SetProperty for String {
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int {
|
unsafe fn set_property(
|
||||||
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error> {
|
||||||
// should add zero terminator directly
|
// should add zero terminator directly
|
||||||
let value = CString::new(self).expect("null bytes in string property value");
|
let value = CString::new(self).expect("null bytes in string property value");
|
||||||
let value_ptr: *const c_char = value.as_ptr();
|
let value_ptr: *const c_char = value.as_ptr();
|
||||||
ffi::mpv_set_property(
|
Error::from_return_code(ffi::mpv_set_property(
|
||||||
ctx,
|
ctx,
|
||||||
name,
|
name,
|
||||||
ffi::mpv_format_MPV_FORMAT_STRING,
|
ffi::mpv_format_MPV_FORMAT_STRING,
|
||||||
std::ptr::from_ref::<*const c_char>(&value_ptr) as *mut c_void,
|
std::ptr::from_ref::<*const c_char>(&value_ptr) as *mut c_void,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SetProperty for &'a str {
|
impl<'a> SetProperty for &'a str {
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int {
|
unsafe fn set_property(
|
||||||
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error> {
|
||||||
// need to add zero terminator
|
// need to add zero terminator
|
||||||
String::set_property(self.into(), ctx, name)
|
String::set_property(self.into(), ctx, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SetProperty for bool {
|
impl SetProperty for bool {
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int {
|
unsafe fn set_property(
|
||||||
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let value: c_int = if self { 1 } else { 0 };
|
let value: c_int = if self { 1 } else { 0 };
|
||||||
ffi::mpv_set_property(
|
Error::from_return_code(ffi::mpv_set_property(
|
||||||
ctx,
|
ctx,
|
||||||
name,
|
name,
|
||||||
ffi::mpv_format_MPV_FORMAT_FLAG,
|
ffi::mpv_format_MPV_FORMAT_FLAG,
|
||||||
std::ptr::from_ref::<c_int>(&value) as *mut c_void,
|
std::ptr::from_ref::<c_int>(&value) as *mut c_void,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SetProperty for i64 {
|
impl SetProperty for i64 {
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int {
|
unsafe fn set_property(
|
||||||
ffi::mpv_set_property(
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
Error::from_return_code(ffi::mpv_set_property(
|
||||||
ctx,
|
ctx,
|
||||||
name,
|
name,
|
||||||
ffi::mpv_format_MPV_FORMAT_INT64,
|
ffi::mpv_format_MPV_FORMAT_INT64,
|
||||||
std::ptr::from_ref::<i64>(&self) as *mut c_void,
|
std::ptr::from_ref::<i64>(&self) as *mut c_void,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SetProperty for f64 {
|
impl SetProperty for f64 {
|
||||||
unsafe fn set_property(self, ctx: *mut ffi::mpv_handle, name: *const c_char) -> c_int {
|
unsafe fn set_property(
|
||||||
ffi::mpv_set_property(
|
self,
|
||||||
|
ctx: *mut ffi::mpv_handle,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
Error::from_return_code(ffi::mpv_set_property(
|
||||||
ctx,
|
ctx,
|
||||||
name,
|
name,
|
||||||
ffi::mpv_format_MPV_FORMAT_DOUBLE,
|
ffi::mpv_format_MPV_FORMAT_DOUBLE,
|
||||||
std::ptr::from_ref::<f64>(&self) as *mut c_void,
|
std::ptr::from_ref::<f64>(&self) as *mut c_void,
|
||||||
)
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetProperty: Sized {
|
||||||
|
/// # Safety
|
||||||
|
/// see mpv_get_property
|
||||||
|
unsafe fn get_property(ctx: *mut ffi::mpv_handle, name: *const c_char) -> Result<Self, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetProperty for bool {
|
||||||
|
unsafe fn get_property(ctx: *mut ffi::mpv_handle, name: *const c_char) -> Result<Self, Error> {
|
||||||
|
let mut value: c_int = -1;
|
||||||
|
Error::from_return_code(ffi::mpv_get_property(
|
||||||
|
ctx,
|
||||||
|
name,
|
||||||
|
ffi::mpv_format_MPV_FORMAT_FLAG,
|
||||||
|
std::ptr::from_mut::<c_int>(&mut value) as *mut c_void,
|
||||||
|
))?;
|
||||||
|
match value {
|
||||||
|
0 => Ok(false),
|
||||||
|
1 => Ok(true),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetProperty for i64 {
|
||||||
|
unsafe fn get_property(ctx: *mut ffi::mpv_handle, name: *const c_char) -> Result<Self, Error> {
|
||||||
|
let mut value: i64 = -1;
|
||||||
|
Error::from_return_code(ffi::mpv_get_property(
|
||||||
|
ctx,
|
||||||
|
name,
|
||||||
|
ffi::mpv_format_MPV_FORMAT_INT64,
|
||||||
|
std::ptr::from_mut::<i64>(&mut value) as *mut c_void,
|
||||||
|
))?;
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{event, ffi, Error, Event as MpvEvent, SetProperty};
|
use super::{event, ffi, Error, Event as MpvEvent, GetProperty, SetProperty};
|
||||||
use event::{
|
use event::{
|
||||||
EndFileEvent, EndFileReason, LogMessageEvent, PropertyEvent, PropertyEventValue, StartFileEvent,
|
EndFileEvent, EndFileReason, HookEvent, LogMessageEvent, PropertyEvent, StartFileEvent,
|
||||||
};
|
};
|
||||||
use event_listener::{Event, EventListener, IntoNotification};
|
use event_listener::{Event, EventListener, IntoNotification};
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
|
@ -83,7 +83,12 @@ impl Handle {
|
||||||
pub fn set_property(&self, name: &str, value: impl SetProperty) -> Result<(), Error> {
|
pub fn set_property(&self, name: &str, value: impl SetProperty) -> 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");
|
||||||
Error::from_return_code(unsafe { value.set_property(self.inner.as_ptr(), name.as_ptr()) })
|
unsafe { value.set_property(self.inner.as_ptr(), name.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_property<T: GetProperty>(&self, name: &str) -> Result<T, Error> {
|
||||||
|
let name = CString::new(name).expect("null bytes in property name");
|
||||||
|
unsafe { T::get_property(self.inner.as_ptr(), name.as_ptr()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn command<'a>(&self, args: impl IntoIterator<Item = &'a str>) -> Result<(), Error> {
|
pub fn command<'a>(&self, args: impl IntoIterator<Item = &'a str>) -> Result<(), Error> {
|
||||||
|
@ -105,14 +110,14 @@ impl Handle {
|
||||||
Error::from_return_code(unsafe { ffi::mpv_command(self.inner.as_ptr(), args) })
|
Error::from_return_code(unsafe { ffi::mpv_command(self.inner.as_ptr(), args) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn observe_property_i64(&self, reply_userdata: u64, name: &str) -> Result<(), Error> {
|
pub fn observe_property(&self, reply_userdata: u64, name: &str) -> Result<(), Error> {
|
||||||
let name = CString::new(name).expect("null bytes in property name");
|
let name = CString::new(name).expect("null bytes in property name");
|
||||||
Error::from_return_code(unsafe {
|
Error::from_return_code(unsafe {
|
||||||
ffi::mpv_observe_property(
|
ffi::mpv_observe_property(
|
||||||
self.inner.as_ptr(),
|
self.inner.as_ptr(),
|
||||||
reply_userdata,
|
reply_userdata,
|
||||||
name.as_ptr(),
|
name.as_ptr(),
|
||||||
ffi::mpv_format_MPV_FORMAT_INT64,
|
ffi::mpv_format_MPV_FORMAT_NONE,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -123,6 +128,19 @@ impl Handle {
|
||||||
Error::from_return_code(rc).map(|()| rc as u32)
|
Error::from_return_code(rc).map(|()| rc as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_hook(&self, reply_userdata: u64, name: &str, priority: i32) -> Result<(), Error> {
|
||||||
|
let name = CString::new(name).expect("null bytes in property name");
|
||||||
|
Error::from_return_code(unsafe {
|
||||||
|
ffi::mpv_hook_add(self.inner.as_ptr(), reply_userdata, name.as_ptr(), priority)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// > It is explicitly undefined behavior to call this more than once for each MPV_EVENT_HOOK, to pass an incorrect ID, or to call this on a mpv_handle different from the one that registered the handler and received the event.
|
||||||
|
pub unsafe fn continue_hook_unchecked(&self, id: u64) -> Result<(), Error> {
|
||||||
|
Error::from_return_code(unsafe { ffi::mpv_hook_continue(self.inner.as_ptr(), id) })
|
||||||
|
}
|
||||||
|
|
||||||
// should take listener before we drain the event queue, so we don't miss any notifications
|
// should take listener before we drain the event queue, so we don't miss any notifications
|
||||||
pub fn wakeup_listener(&self) -> EventListener {
|
pub fn wakeup_listener(&self) -> EventListener {
|
||||||
self.wakeup.listen()
|
self.wakeup.listen()
|
||||||
|
@ -196,13 +214,17 @@ impl Handle {
|
||||||
name: unsafe { CStr::from_ptr(data.name) }
|
name: unsafe { CStr::from_ptr(data.name) }
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.into(),
|
.into(),
|
||||||
value: match data.format {
|
}))
|
||||||
ffi::mpv_format_MPV_FORMAT_NONE => PropertyEventValue::None,
|
}
|
||||||
ffi::mpv_format_MPV_FORMAT_INT64 => {
|
|
||||||
PropertyEventValue::Int64(*unsafe { &*(data.data as *mut i64) })
|
ffi::mpv_event_id_MPV_EVENT_HOOK => {
|
||||||
}
|
let data = unsafe { &*(event.data as *mut ffi::mpv_event_hook) };
|
||||||
_ => todo!("{:?}", data.format),
|
Some(MpvEvent::Hook(HookEvent {
|
||||||
},
|
reply_userdata: event.reply_userdata,
|
||||||
|
name: unsafe { CStr::from_ptr(data.name) }
|
||||||
|
.to_string_lossy()
|
||||||
|
.into(),
|
||||||
|
id: data.id,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
175
src/playbin2.rs
175
src/playbin2.rs
|
@ -1,11 +1,33 @@
|
||||||
use crate::mpv;
|
use crate::mpv;
|
||||||
|
use crate::signal::SignalEmitter;
|
||||||
use event_listener::EventListener;
|
use event_listener::EventListener;
|
||||||
|
use std::cell::{Ref, RefCell};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub struct Playbin {
|
pub trait PlaybinEntry {
|
||||||
mpv: mpv::Handle,
|
fn url(&self) -> &Url;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Playbin {
|
impl PlaybinEntry for Url {
|
||||||
|
fn url(&self) -> &Url {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// E: generic entry type
|
||||||
|
pub struct Playbin<E> {
|
||||||
|
mpv: mpv::Handle,
|
||||||
|
entries: RefCell<Vec<E>>,
|
||||||
|
|
||||||
|
paused_changed: SignalEmitter<()>,
|
||||||
|
current_entry_changed: SignalEmitter<()>,
|
||||||
|
|
||||||
|
entry_inserted: SignalEmitter<u32>,
|
||||||
|
stopped: SignalEmitter<()>,
|
||||||
|
entry_removed: SignalEmitter<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> Default for Playbin<E> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mpv = mpv::Handle::new();
|
let mpv = mpv::Handle::new();
|
||||||
mpv.set_property("audio-client-name", "audrey").unwrap();
|
mpv.set_property("audio-client-name", "audrey").unwrap();
|
||||||
|
@ -14,14 +36,118 @@ impl Default for Playbin {
|
||||||
mpv.set_property("prefetch-playlist", true).unwrap();
|
mpv.set_property("prefetch-playlist", true).unwrap();
|
||||||
mpv.set_property("gapless-audio", true).unwrap();
|
mpv.set_property("gapless-audio", true).unwrap();
|
||||||
|
|
||||||
mpv.command(["loadfile", "https://www.youtube.com/watch?v=19y8YTbvri8"])
|
mpv.observe_property(0, "pause").unwrap();
|
||||||
.unwrap();
|
mpv.observe_property(1, "playlist-pos").unwrap();
|
||||||
|
|
||||||
Self { mpv }
|
// "Useful to drain property changes before a new file is loaded."
|
||||||
|
mpv.add_hook(0, "on_before_start_file", 0).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
mpv,
|
||||||
|
entries: RefCell::new(vec![]),
|
||||||
|
|
||||||
|
paused_changed: Default::default(),
|
||||||
|
current_entry_changed: Default::default(),
|
||||||
|
|
||||||
|
entry_inserted: Default::default(),
|
||||||
|
stopped: Default::default(),
|
||||||
|
entry_removed: Default::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Playbin {
|
impl<E> Playbin<E>
|
||||||
|
where
|
||||||
|
E: PlaybinEntry,
|
||||||
|
{
|
||||||
|
pub fn paused(&self) -> bool {
|
||||||
|
self.mpv.get_property("pause").unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_paused(&self, paused: bool) {
|
||||||
|
self.mpv.set_property("pause", paused).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(&self) -> Option<f64> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_entry(&self) -> Option<u32> {
|
||||||
|
self.mpv
|
||||||
|
.get_property::<i64>("playlist-pos")
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seek(&self, _position: f64) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_entry(&self) {
|
||||||
|
self.mpv.command(["playlist-next"]).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prev_entry(&self) {
|
||||||
|
self.mpv.command(["playlist-prev"]).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn play_entry(&self, index: u32) {
|
||||||
|
self.mpv
|
||||||
|
.command(["playlist-play-index", &index.to_string()])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entries(&self) -> Ref<'_, [E]> {
|
||||||
|
Ref::map(self.entries.borrow(), Vec::as_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_entry(&self, entry: E) {
|
||||||
|
let mut entries = self.entries.borrow_mut();
|
||||||
|
self.mpv
|
||||||
|
.command(["loadfile", entry.url().as_str(), "append-play"])
|
||||||
|
.unwrap();
|
||||||
|
let index = entries.len();
|
||||||
|
entries.push(entry);
|
||||||
|
|
||||||
|
drop(entries);
|
||||||
|
self.entry_inserted.emit(index as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_entry(&self, index: u32, entry: E) {
|
||||||
|
let mut entries = self.entries.borrow_mut();
|
||||||
|
self.mpv
|
||||||
|
.command(["loadfile", entry.url().as_str(), "insert-at-play"])
|
||||||
|
.unwrap();
|
||||||
|
entries.insert(index as usize, entry);
|
||||||
|
|
||||||
|
drop(entries);
|
||||||
|
self.entry_inserted.emit(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop playback and clear playlist
|
||||||
|
pub fn stop(&self) {
|
||||||
|
let mut entries = self.entries.borrow_mut();
|
||||||
|
self.mpv.command(["stop"]).unwrap();
|
||||||
|
entries.clear();
|
||||||
|
|
||||||
|
drop(entries);
|
||||||
|
self.stopped.emit(());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_entry(&self, index: u32) {
|
||||||
|
let mut entries = self.entries.borrow_mut();
|
||||||
|
self.mpv.command(["remove", &index.to_string()]).unwrap();
|
||||||
|
entries.remove(index as usize);
|
||||||
|
|
||||||
|
drop(entries);
|
||||||
|
self.entry_removed.emit(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_entry(&self, _from: u32, _to: u32) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tick(&self) -> EventListener {
|
pub fn tick(&self) -> EventListener {
|
||||||
let listener = self.mpv.wakeup_listener();
|
let listener = self.mpv.wakeup_listener();
|
||||||
while let Some(event) = self.mpv.wait_event(0.0) {
|
while let Some(event) = self.mpv.wait_event(0.0) {
|
||||||
|
@ -31,11 +157,42 @@ impl Playbin {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_event(&self, event: mpv::Event) {
|
fn handle_event(&self, event: mpv::Event) {
|
||||||
println!("mpv event {:?}", event);
|
match event {
|
||||||
|
mpv::Event::PropertyChange(event) => match event.reply_userdata {
|
||||||
|
0 => {
|
||||||
|
assert_eq!(&event.name, "pause");
|
||||||
|
self.paused_changed.emit(());
|
||||||
|
println!("new paused! {:?}", self.paused());
|
||||||
|
}
|
||||||
|
|
||||||
|
1 => {
|
||||||
|
assert_eq!(&event.name, "playlist-pos");
|
||||||
|
self.current_entry_changed.emit(());
|
||||||
|
println!("new current_entry! {:?}", self.current_entry());
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
|
||||||
|
mpv::Event::Hook(event) => match event.reply_userdata {
|
||||||
|
0 => {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => println!("mpv event {:?}", event),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Playbin {
|
impl<E> Drop for Playbin<E> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
println!("dropping Playbin2");
|
println!("dropping Playbin2");
|
||||||
self.mpv.command(["quit"]).unwrap();
|
self.mpv.command(["quit"]).unwrap();
|
||||||
|
|
|
@ -28,7 +28,7 @@ mod imp {
|
||||||
pub(super) setup: crate::ui::Setup,
|
pub(super) setup: crate::ui::Setup,
|
||||||
pub(super) api: RefCell<Option<crate::subsonic_vala::Client>>,
|
pub(super) api: RefCell<Option<crate::subsonic_vala::Client>>,
|
||||||
|
|
||||||
playbin2: Rc<crate::playbin2::Playbin>,
|
playbin2: Rc<crate::playbin2::Playbin<url::Url>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
@ -52,6 +52,13 @@ mod imp {
|
||||||
fn constructed(&self) {
|
fn constructed(&self) {
|
||||||
self.parent_constructed();
|
self.parent_constructed();
|
||||||
|
|
||||||
|
self.playbin2.tick();
|
||||||
|
self.playbin2.push_entry(
|
||||||
|
"https://www.youtube.com/watch?v=19y8YTbvri8"
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
let playbin = Rc::downgrade(&self.playbin2);
|
let playbin = Rc::downgrade(&self.playbin2);
|
||||||
glib::spawn_future_local(glib::clone!(async move {
|
glib::spawn_future_local(glib::clone!(async move {
|
||||||
loop {
|
loop {
|
||||||
|
|
Loading…
Reference in a new issue