diff --git a/src/ui/window.rs b/src/ui/window.rs index 83c5b56..6fcde63 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -11,10 +11,22 @@ mod imp { use tracing::{event, span, Level}; use zbus::object_server::InterfaceRef; + #[derive(Debug, Copy, Clone)] + enum State { + Idle, + FileLoading, + FileLoaded, + Active, + FileEnded, + Seeking, + } + #[derive(gtk::CompositeTemplate, glib::Properties)] #[template(resource = "/eu/callcc/audrey/window.ui")] #[properties(wrapper_type = super::Window)] pub struct Window { + state: Cell, + #[template_child] pub(super) playbar: TemplateChild, @@ -92,6 +104,8 @@ mod imp { mpv.add_hook(0, "on_before_start_file", 0).unwrap(); Self { + state: Cell::new(State::Idle), + playbar: Default::default(), play_queue: Default::default(), can_click_shuffle_all: Cell::new(false), @@ -427,6 +441,9 @@ mod imp { 4 => { assert_eq!(event.name, "idle-active"); self.obj().notify("idle-active"); + if self.obj().idle_active() { + self.on_idle_active(); + } } 6 => { @@ -487,7 +504,25 @@ mod imp { }; } + fn on_idle_active(&self) { + match self.state.get() { + State::Idle => {} + State::FileEnded => {} + + other => panic!("invalid state transition: IdleActive from {other:?}"), + } + self.state.set(State::Idle); + } + fn on_start_file(&self) { + match self.state.get() { + State::Idle => {} + State::FileEnded => {} + + other => panic!("invalid state transition: StartFile from {other:?}"), + } + self.state.set(State::FileLoading); + event!(Level::INFO, "StartFile"); self.obj().notify("song"); self.buffering_start(); @@ -526,6 +561,13 @@ mod imp { } fn on_file_loaded(&self) { + match self.state.get() { + State::FileLoading => {} + + other => panic!("invalid state transition: FileLoaded from {other:?}"), + } + self.state.set(State::FileLoaded); + event!(Level::INFO, "FileLoaded"); // sanity check // i think "path" is only available after this event is dispatched @@ -537,10 +579,27 @@ mod imp { fn on_seek(&self) { event!(Level::INFO, "Seek"); + + match self.state.get() { + State::Active => {} + State::Seeking => {} + + other => panic!("invalid state transition: Seek from {other:?}"), + } + self.state.set(State::Seeking); + self.buffering_start(); } fn on_playback_restart(&self) { + match self.state.get() { + State::FileLoaded => {} + State::Seeking => {} + + other => panic!("invalid state transition: PlaybackRestart from {other:?}"), + } + self.state.set(State::Active); + event!(Level::INFO, "PlaybackRestart"); self.buffering_end(); self.obj().notify("time-pos"); @@ -554,6 +613,16 @@ mod imp { fn on_end_file(&self, event: crate::mpv::event::EndFileEvent) { event!(Level::INFO, "EndFile: {event:?}"); + + match self.state.get() { + State::Active => {} + State::FileLoading => {} + State::Seeking => {} + + other => panic!("invalid state transition: EndFile from {other:?}"), + } + self.state.set(State::FileEnded); + self.obj().notify("song"); self.buffering_end();