diff --git a/src/ui/window.rs b/src/ui/window.rs index 510b031..343f960 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -166,132 +166,13 @@ mod imp { use crate::mpv::Event; match event { - Event::PropertyChange(event) => match event.reply_userdata { - 0 => { - assert_eq!(event.name, "volume"); - window.notify("volume"); - } - - 1 => { - assert_eq!(event.name, "mute"); - window.notify("mute"); - } - - 2 => { - assert_eq!(event.name, "pause"); - window.notify("pause"); - } - - 3 => { - assert_eq!(event.name, "playlist-pos"); - window.notify("playlist-pos"); - } - - 4 => { - assert_eq!(event.name, "idle-active"); - window.notify("idle-active"); - } - - 6 => { - assert_eq!(event.name, "playlist-count"); - window.notify("playlist-count"); - } - - 7 => { - assert_eq!(event.name, "duration"); - window.notify("duration"); - } - - 8 => { - assert_eq!(event.name, "path"); - // sanity check - match window.imp().mpv.get_property::("path") { - Ok(path) => { - assert_eq!(path, window.song().unwrap().stream_url()) - } - Err(err) if err.is_property_unavailable() => {} - Err(err) => Err(err).unwrap(), - } - } - - _ => unreachable!(), - }, - - Event::StartFile(_) => { - event!(Level::INFO, "start file event"); - window.notify("song"); - window.imp().buffering_start(); - - let window2 = window.clone(); - let song_id = window.song().unwrap().id(); - window - .imp() - .loading_cover_handle - .replace(Some(glib::spawn_future_local(async move { - let api = window2.imp().api.borrow().as_ref().unwrap().clone(); - let bytes = - api - .cover_art(&song_id) - .await - .expect("could not load cover art for song {song_id}"); - - match window2.song() { - Some(song) if song.id() == song_id => { - let texture = gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)).expect( - "could not create texture from cover art for {song_id}", - ); - window2.set_playing_cover_art(Some(texture)); - } - _ => { event!(Level::WARN, "was too late to fetch cover for song {song_id}") }, - } - }))) - .map(|handle| handle.abort()); - - // make sure this is reported as 0 - window.notify("time-pos"); - } - - Event::Hook(event) => match event.reply_userdata { - 0 => { - assert_eq!(&event.name, "on_before_start_file"); - event!(Level::DEBUG, "on_before_start_file triggered"); - // just use this as a barrier - window.imp().mpv.continue_hook(event.id).unwrap(); - } - - _ => unreachable!(), - }, - - Event::LogMessage(event) => { - let span = span!(Level::DEBUG, "mpv_log", prefix = event.prefix); - let _guard = span.enter(); - match event.log_level { - // level has to be 'static so this sux - l if l <= 20 => { - event!(target: "mpv_event", Level::ERROR, "{}", event.text.trim()) - } - l if l <= 30 => { - event!(target: "mpv_event", Level::WARN, "{}", event.text.trim()) - } - l if l <= 40 => { - event!(target: "mpv_event", Level::INFO, "{}", event.text.trim()) - } - l if l <= 60 => { - event!(target: "mpv_event", Level::DEBUG, "{}", event.text.trim()) - } - l if l <= 70 => { - event!(target: "mpv_event", Level::TRACE, "{}", event.text.trim()) - } - // should be unused - _ => event!( - target: "mpv_erroneus_event", - Level::DEBUG, - log_level = event.log_level, - "{}", - event.text.trim(), - ), - }; - } + Event::PropertyChange(event) => window.imp().on_property_change(event), + Event::StartFile(_) => window.imp().on_start_file(), + Event::Hook(event) => window.imp().on_hook(event), + Event::LogMessage(event) => window.imp().on_log_message(event), + Event::Seek => window.imp().on_seek(), + Event::PlaybackRestart => window.imp().on_playback_restart(), + Event::EndFile(event) => window.imp().on_end_file(event), Event::Unknown(_) => { // either deprecated or future, ignore @@ -302,41 +183,6 @@ mod imp { // ^ ignore } - Event::Seek => { - event!(Level::INFO, "seek event"); - window.imp().buffering_start(); - } - - Event::PlaybackRestart => { - event!(Level::INFO, "playback restart event"); - window.imp().buffering_end(); - window.notify("time-pos"); - - if let Some(queued_seek) = window.imp().queued_seek.take() { - // a seek was tried before and failed, try again now - event!(Level::INFO, "performing queued seek to {queued_seek}"); - window.seek(queued_seek); - } - } - - Event::EndFile(event) => { - event!(Level::INFO, "end file event: {event:?}"); - window.notify("song"); - window.imp().buffering_end(); - - if let Err(err) = event.reason { - event!(Level::ERROR, "end file error: {err}"); - } - - // cancel queued seek always - window.imp().queued_seek.set(None); - - window.set_playing_cover_art(None::); - - // make sure the seekbar looks full - window.notify("time-pos"); - } - _ => event!(Level::DEBUG, "unhandled {event:?}"), } } @@ -558,6 +404,174 @@ mod imp { self.buffering_timeout.take().map(|source| source.remove()); self.playbar.set_show_pulse_bar(false); } + + fn on_property_change(&self, event: crate::mpv::event::PropertyEvent) { + match event.reply_userdata { + 0 => { + assert_eq!(event.name, "volume"); + self.obj().notify("volume"); + } + + 1 => { + assert_eq!(event.name, "mute"); + self.obj().notify("mute"); + } + + 2 => { + assert_eq!(event.name, "pause"); + self.obj().notify("pause"); + } + + 3 => { + assert_eq!(event.name, "playlist-pos"); + self.obj().notify("playlist-pos"); + } + + 4 => { + assert_eq!(event.name, "idle-active"); + self.obj().notify("idle-active"); + } + + 6 => { + assert_eq!(event.name, "playlist-count"); + self.obj().notify("playlist-count"); + } + + 7 => { + assert_eq!(event.name, "duration"); + self.obj().notify("duration"); + } + + 8 => { + assert_eq!(event.name, "path"); + // sanity check + match self.mpv.get_property::("path") { + Ok(path) => { + assert_eq!(path, self.obj().song().unwrap().stream_url()) + } + Err(err) if err.is_property_unavailable() => {} + Err(err) => Err(err).unwrap(), + } + } + + _ => unreachable!(), + } + } + + fn on_start_file(&self) { + event!(Level::INFO, "start file event"); + self.obj().notify("song"); + self.buffering_start(); + + let window = self.obj().clone(); + let song_id = window.song().unwrap().id(); + self + .loading_cover_handle + .replace(Some(glib::spawn_future_local(async move { + let api = window.imp().api.borrow().as_ref().unwrap().clone(); + let bytes = api + .cover_art(&song_id) + .await + .expect("could not load cover art for song {song_id}"); + + match window.song() { + Some(song) if song.id() == song_id => { + let texture = gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)) + .expect("could not create texture from cover art for {song_id}"); + window.set_playing_cover_art(Some(texture)); + } + _ => { + event!( + Level::WARN, + "was too late to fetch cover for song {song_id}" + ) + } + } + }))) + .map(|handle| handle.abort()); + + // make sure this is reported as 0 + self.obj().notify("time-pos"); + } + + fn on_hook(&self, event: crate::mpv::event::HookEvent) { + match event.reply_userdata { + 0 => { + assert_eq!(&event.name, "on_before_start_file"); + event!(Level::DEBUG, "on_before_start_file triggered"); + // just use this as a barrier + self.mpv.continue_hook(event.id).unwrap(); + } + + _ => unreachable!(), + } + } + + fn on_log_message(&self, event: crate::mpv::event::LogMessageEvent) { + let span = span!(Level::DEBUG, "mpv_log", prefix = event.prefix); + let _guard = span.enter(); + match event.log_level { + // level has to be 'static so this sux + l if l <= 20 => { + event!(target: "mpv_event", Level::ERROR, "{}", event.text.trim()) + } + l if l <= 30 => { + event!(target: "mpv_event", Level::WARN, "{}", event.text.trim()) + } + l if l <= 40 => { + event!(target: "mpv_event", Level::INFO, "{}", event.text.trim()) + } + l if l <= 60 => { + event!(target: "mpv_event", Level::DEBUG, "{}", event.text.trim()) + } + l if l <= 70 => { + event!(target: "mpv_event", Level::TRACE, "{}", event.text.trim()) + } + // should be unused + _ => event!( + target: "mpv_erroneus_event", + Level::DEBUG, + log_level = event.log_level, + "{}", + event.text.trim(), + ), + }; + } + + fn on_seek(&self) { + event!(Level::INFO, "seek event"); + self.buffering_start(); + } + + fn on_playback_restart(&self) { + event!(Level::INFO, "playback restart event"); + self.buffering_end(); + self.obj().notify("time-pos"); + + if let Some(queued_seek) = self.queued_seek.take() { + // a seek was tried before and failed, try again now + event!(Level::INFO, "performing queued seek to {queued_seek}"); + self.obj().seek(queued_seek); + } + } + + fn on_end_file(&self, event: crate::mpv::event::EndFileEvent) { + event!(Level::INFO, "end file event: {event:?}"); + self.obj().notify("song"); + self.buffering_end(); + + if let Err(err) = event.reason { + event!(Level::ERROR, "end file error: {err}"); + } + + // cancel queued seek always + self.queued_seek.set(None); + + self.obj().set_playing_cover_art(None::); + + // make sure the seekbar looks full + self.obj().notify("time-pos"); + } } impl Drop for Window {