diff --git a/examples/events.rs b/examples/events.rs index c00053e..98fdcdb 100644 --- a/examples/events.rs +++ b/examples/events.rs @@ -18,21 +18,24 @@ use libmpv::{events::*, *}; -use std::{env, thread, time::Duration}; +use std::{collections::HashMap, env, thread, time::Duration}; -fn main() { +const VIDEO_URL: &str = "https://www.youtube.com/watch?v=DLzxrzFCyOs"; + +fn main() -> Result<()> { let path = env::args() .nth(1) - .unwrap_or_else(|| String::from("https://www.youtube.com/watch?v=DLzxrzFCyOs")); + .unwrap_or_else(|| String::from(VIDEO_URL)); // Create an `Mpv` and set some properties. - let mpv = Mpv::new().unwrap(); - mpv.set_property("volume", 15).unwrap(); - mpv.set_property("vo", "null").unwrap(); + let mpv = Mpv::new()?; + mpv.set_property("volume", 15)?; + mpv.set_property("vo", "null")?; let mut ev_ctx = mpv.create_event_context(); - ev_ctx.disable_deprecated_events().unwrap(); - ev_ctx.observe_property("volume", Format::Int64, 0).unwrap(); + ev_ctx.disable_deprecated_events()?; + ev_ctx.observe_property("volume", Format::Int64, 0)?; + ev_ctx.observe_property("demuxer-cache-state", Format::Node, 0)?; crossbeam::scope(|scope| { scope.spawn(|_| { @@ -49,16 +52,42 @@ fn main() { mpv.playlist_next_force().unwrap(); }); scope.spawn(move |_| loop { - let ev = ev_ctx.wait_event(600.); - if let Some(Ok(Event::EndFile(r))) = ev { - println!("Exiting! Reason: {:?}", r); - break; - } else if let Some(Ok(e)) = ev { - println!("Event triggered: {:?}", e); - } else if let Some(Err(e)) = ev { - println!("Event errored: {:?}", e); + let ev = ev_ctx.wait_event(600.).unwrap_or(Err(Error::Null)); + + match ev { + Ok(Event::EndFile(r)) => { + println!("Exiting! Reason: {:?}", r); + break; + } + + Ok(Event::PropertyChange { + name: "demuxer-cache-state", + change: PropertyData::Node(mpv_node), + .. + }) => { + let ranges = seekable_ranges(mpv_node).unwrap(); + println!("Seekable ranges updated: {:?}", ranges); + } + Ok(e) => println!("Event triggered: {:?}", e), + Err(e) => println!("Event errored: {:?}", e), } }); }) .unwrap(); + Ok(()) +} + +fn seekable_ranges(demuxer_cache_state: &MpvNode) -> Option> { + let mut res = Vec::new(); + let props: HashMap<&str, MpvNode> = demuxer_cache_state.to_map()?.collect(); + let ranges = props.get("seekable-ranges")?.to_array()?; + + for node in ranges { + let range: HashMap<&str, MpvNode> = node.to_map()?.collect(); + let start = range.get("start")?.to_f64()?; + let end = range.get("end")?.to_f64()?; + res.push((start, end)); + } + + Some(res) }