diff --git a/src/mpv/event.rs b/src/mpv/event.rs index 2617ce4..cebe92f 100644 --- a/src/mpv/event.rs +++ b/src/mpv/event.rs @@ -62,6 +62,7 @@ pub struct PropertyEvent { pub enum PropertyEventValue { Int64(i64), Double(f64), + String(String), } #[derive(Clone, Debug)] diff --git a/src/mpv/handle.rs b/src/mpv/handle.rs index e55e6b6..aada46d 100644 --- a/src/mpv/handle.rs +++ b/src/mpv/handle.rs @@ -165,6 +165,18 @@ impl Handle { }) } + pub fn observe_property_string(&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_STRING, + ) + }) + } + pub fn unobserve_property(&self, registered_reply_userdata: u64) -> Result { let rc = unsafe { ffi::mpv_unobserve_property(self.inner.as_ptr(), registered_reply_userdata) }; @@ -281,6 +293,12 @@ impl Handle { *(data.data as *mut f64) })) } + ffi::mpv_format_MPV_FORMAT_STRING => { + let value = unsafe { CStr::from_ptr(*(data.data as *mut *mut c_char)) }; + Some(PropertyEventValue::String( + String::from_utf8_lossy(value.to_bytes()).into_owned(), + )) + } _ => todo!(), }, })) diff --git a/src/ui/window.rs b/src/ui/window.rs index aaadc01..61a961b 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -97,6 +97,7 @@ mod imp { mpv.set_property("vid", false).unwrap(); mpv.set_property("prefetch-playlist", true).unwrap(); + mpv.observe_property_string(0, "path").unwrap(); mpv.observe_property_int64(3, "playlist-pos").unwrap(); mpv.observe_property(4, "idle-active").unwrap(); mpv.observe_property(6, "playlist-count").unwrap(); @@ -473,12 +474,15 @@ mod imp { } fn idle_active(&self) -> bool { - self.mpv.get_property("idle-active").unwrap() + match self.state.get() { + State::Idle => true, + _ => false, + } } fn playlist_count(&self) -> i64 { let count = self.mpv.get_property::("playlist-count").unwrap(); - assert_eq!(count as u32, self.playlist_model.n_items()); + assert_eq!(count as u32, self.playlist_model.n_items()); // sanity check count } @@ -530,6 +534,18 @@ mod imp { use crate::mpv::event::PropertyEventValue; match event.reply_userdata { + 0 => { + /* FIXME: can happen before playlist-pos is updated + assert_eq!(event.name, "path"); + match event.value { + None => {} + Some(PropertyEventValue::String(s)) => { + // sanity check + assert_eq!(self.obj().song().unwrap().stream_url(), s); + } + _ => unreachable!(), + }*/ + } 3 => { assert_eq!(event.name, "playlist-pos"); let value = match event.value { @@ -567,6 +583,17 @@ mod imp { self.duration.set(value); event!(Level::TRACE, "duration is now {value} (from mpv)"); self.obj().notify("duration"); + + { + let left = value as i64; + let right = self.song().unwrap().duration(); + if left != right { + event!( + Level::WARN, + "mpv duration {left:?} doesn not match subsonic duration {right:?}" + ); + } + } } _ => unreachable!(), @@ -707,23 +734,6 @@ mod imp { self.state.set(State::FileLoaded); event!(Level::INFO, "FileLoaded"); - // sanity check - // i think "path" is only available after this event is dispatched - assert_eq!( - self.mpv.get_property::("path").unwrap(), - self.obj().song().unwrap().stream_url() - ); - // same with "duration" - { - let left = self.mpv.get_property::("duration").unwrap() as i64; - let right = self.song().unwrap().duration(); - if left != right { - event!( - Level::WARN, - "mpv duration {left:?} doesn not match subsonic duration {right:?}" - ); - } - } } fn on_seek(&self) {