diff --git a/src/mpv.rs b/src/mpv.rs index a287984..c84f1d5 100644 --- a/src/mpv.rs +++ b/src/mpv.rs @@ -9,5 +9,5 @@ pub use format::SetProperty; mod handle; pub use handle::Handle; -mod event; -pub use event::{EndFileEvent, EndFileReason, Event, LogMessageEvent, StartFileEvent}; +pub mod event; +pub use event::Event; diff --git a/src/mpv/event.rs b/src/mpv/event.rs index e8fa1f4..788d352 100644 --- a/src/mpv/event.rs +++ b/src/mpv/event.rs @@ -1,6 +1,7 @@ use super::Error; +use std::borrow::Cow; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub enum Event<'a> { Shutdown, LogMessage(LogMessageEvent<'a>), @@ -15,18 +16,18 @@ pub enum Event<'a> { AudioReconfig, //Seek, PlaybackRestart, - //PropertyChange, + PropertyChange(PropertyEvent<'a>), //QueueOverflow, //Hook, Unknown(u32), } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct StartFileEvent { pub playlist_entry_id: i64, } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub enum EndFileReason { Eof, Stop, @@ -35,7 +36,7 @@ pub enum EndFileReason { Unknown(u32), } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct EndFileEvent { pub reason: Result, pub playlist_entry_id: i64, @@ -43,10 +44,27 @@ pub struct EndFileEvent { pub playlist_insert_num_entries: i32, } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct LogMessageEvent<'a> { pub prefix: &'a str, pub level: &'a str, pub text: &'a str, //log_level: i32, } + +#[derive(Clone, Debug)] +pub struct PropertyEvent<'a> { + pub reply_userdata: u64, + pub name: &'a str, + pub value: PropertyEventValue<'a>, +} + +#[derive(Clone, Debug)] +pub enum PropertyEventValue<'a> { + None, + String(Cow<'a, str>), + OsdString(&'a str), + Flag(bool), + Int64(i64), + Double(f64), +} diff --git a/src/mpv/handle.rs b/src/mpv/handle.rs index d733a13..731b99a 100644 --- a/src/mpv/handle.rs +++ b/src/mpv/handle.rs @@ -1,6 +1,6 @@ -use super::{ - ffi, EndFileEvent, EndFileReason, Error, Event as MpvEvent, LogMessageEvent, SetProperty, - StartFileEvent, +use super::{event, ffi, Error, Event as MpvEvent, SetProperty}; +use event::{ + EndFileEvent, EndFileReason, LogMessageEvent, PropertyEvent, PropertyEventValue, StartFileEvent, }; use event_listener::{Event, EventListener, IntoNotification}; use std::ffi::{c_char, c_void, CStr, CString}; @@ -99,6 +99,24 @@ impl Handle { 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> { + let name = CString::new(name).expect("null bytes in property name"); + Error::from_return_code(unsafe { + ffi::mpv_observe_property( + self.inner.as_ptr(), + reply_userdata, + name.as_ptr(), + ffi::mpv_format_MPV_FORMAT_INT64, + ) + }) + } + + pub fn unobserve_property(&self, registered_reply_userdata: u64) -> Result { + let rc = + unsafe { ffi::mpv_unobserve_property(self.inner.as_ptr(), registered_reply_userdata) }; + Error::from_return_code(rc).map(|()| rc as u32) + } + // 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() @@ -156,6 +174,21 @@ impl Handle { })) } + ffi::mpv_event_id_MPV_EVENT_PROPERTY_CHANGE => { + let data = unsafe { &*(event.data as *mut ffi::mpv_event_property) }; + Some(MpvEvent::PropertyChange(PropertyEvent { + reply_userdata: event.reply_userdata, + name: unsafe { CStr::from_ptr(data.name) }.to_str().unwrap(), + 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) }) + } + _ => todo!("{:?}", data.format), + }, + })) + } + 11 => Some(MpvEvent::Unknown(event.event_id)), _ => todo!("event {}", event.event_id), diff --git a/src/ui/window.rs b/src/ui/window.rs index a50680a..d862380 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -59,7 +59,7 @@ mod imp { mpv.set_property("video", false).unwrap(); mpv.set_property("prefetch-playlist", true).unwrap(); mpv.set_property("gapless-audio", true).unwrap(); - // TODO: observe properties + mpv.observe_property_i64(0, "duration").unwrap(); mpv.command(["loadfile", "https://www.youtube.com/watch?v=19y8YTbvri8"]) .unwrap();