abstract buffering pulse thing
This commit is contained in:
parent
f8a6e09866
commit
455bf60433
4 changed files with 72 additions and 37 deletions
|
@ -17,6 +17,8 @@ use gtk::{gio, glib};
|
|||
|
||||
pub mod mpv;
|
||||
|
||||
pub mod util;
|
||||
|
||||
fn init_tracing() {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::model::Song;
|
||||
use crate::util::buffering::BufferingPulseController;
|
||||
use crate::{mpris, mpv};
|
||||
use adw::prelude::*;
|
||||
use adw::subclass::prelude::*;
|
||||
use glib::subclass::InitializingObject;
|
||||
use glib::JoinHandle;
|
||||
use gtk::{gdk, gio, glib};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cell::{Cell, OnceCell, RefCell};
|
||||
use std::rc::Rc;
|
||||
use tracing::{event, span, Level};
|
||||
use zbus::object_server::InterfaceRef;
|
||||
|
@ -78,7 +79,8 @@ mod imp {
|
|||
|
||||
loading_cover_handle: RefCell<Option<JoinHandle<()>>>,
|
||||
|
||||
buffering_timeout: Cell<Option<glib::SourceId>>,
|
||||
playbar_buffering: OnceCell<BufferingPulseController>,
|
||||
|
||||
time_pos_notify_timeout: Cell<Option<glib::SourceId>>,
|
||||
|
||||
mpris_player: RefCell<Option<InterfaceRef<mpris::Player>>>,
|
||||
|
@ -140,7 +142,8 @@ mod imp {
|
|||
|
||||
loading_cover_handle: Default::default(),
|
||||
|
||||
buffering_timeout: Default::default(),
|
||||
playbar_buffering: Default::default(),
|
||||
|
||||
time_pos_notify_timeout: Default::default(),
|
||||
|
||||
mpris_player: Default::default(),
|
||||
|
@ -539,33 +542,9 @@ mod imp {
|
|||
)
|
||||
}
|
||||
|
||||
fn buffering_start(&self) {
|
||||
let started_buffering = std::time::Instant::now();
|
||||
let window = self.obj().downgrade();
|
||||
if let Some(source) = self.buffering_timeout.replace(Some(glib::timeout_add_local(
|
||||
std::time::Duration::from_millis(100),
|
||||
move || {
|
||||
window
|
||||
.upgrade()
|
||||
.map_or(glib::ControlFlow::Break, move |window| {
|
||||
// 3 second period from gnome hig
|
||||
if started_buffering.elapsed() > std::time::Duration::from_secs(3) {
|
||||
window.imp().playbar.set_show_pulse_bar(true);
|
||||
window.imp().playbar.pulse_bar().pulse();
|
||||
}
|
||||
glib::ControlFlow::Continue
|
||||
})
|
||||
},
|
||||
))) {
|
||||
source.remove()
|
||||
}
|
||||
}
|
||||
|
||||
fn buffering_end(&self) {
|
||||
if let Some(source) = self.buffering_timeout.take() {
|
||||
source.remove();
|
||||
}
|
||||
self.playbar.set_show_pulse_bar(false);
|
||||
fn playbar_buffering(&self) -> &BufferingPulseController {
|
||||
self.playbar_buffering
|
||||
.get_or_init(|| BufferingPulseController::new(&self.playbar.pulse_bar()))
|
||||
}
|
||||
|
||||
fn on_property_change(&self, event: crate::mpv::event::PropertyEvent) {
|
||||
|
@ -734,7 +713,7 @@ mod imp {
|
|||
|
||||
event!(target: "audrey::playback", Level::DEBUG, "StartFile");
|
||||
self.obj().notify("song");
|
||||
self.buffering_start();
|
||||
self.playbar_buffering().start();
|
||||
|
||||
let song = self.obj().song().unwrap();
|
||||
|
||||
|
@ -879,7 +858,7 @@ mod imp {
|
|||
self.state.set(State::Seeking);
|
||||
|
||||
self.obj().notify("time-pos");
|
||||
self.buffering_start();
|
||||
self.playbar_buffering().stop();
|
||||
|
||||
let time_pos = self.obj().time_pos();
|
||||
if let Some(iface_ref) = self.mpris_player() {
|
||||
|
@ -910,7 +889,7 @@ mod imp {
|
|||
self.state.set(State::Active);
|
||||
|
||||
event!(target: "audrey::playback", Level::DEBUG, "PlaybackRestart");
|
||||
self.buffering_end();
|
||||
self.playbar_buffering().stop();
|
||||
|
||||
if let Some(queued_seek) = self.queued_seek.take() {
|
||||
// a seek was tried before and failed, try again now
|
||||
|
@ -943,7 +922,7 @@ mod imp {
|
|||
self.obj().notify("time-pos");
|
||||
|
||||
self.obj().notify("song");
|
||||
self.buffering_end();
|
||||
self.playbar_buffering().stop();
|
||||
|
||||
if let Err(err) = event.reason {
|
||||
event!(Level::ERROR, "end file error: {err}");
|
||||
|
@ -964,9 +943,6 @@ mod imp {
|
|||
if let Some(source) = self.time_pos_notify_timeout.take() {
|
||||
source.remove();
|
||||
}
|
||||
if let Some(source) = self.buffering_timeout.take() {
|
||||
source.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
src/util.rs
Normal file
1
src/util.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod buffering;
|
56
src/util/buffering.rs
Normal file
56
src/util/buffering.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use adw::{glib, prelude::*};
|
||||
use std::cell::Cell;
|
||||
use std::time::Duration;
|
||||
|
||||
// gnome HIG: "Progress needs to be indicated whenever an operation takes more than around three
|
||||
// seconds."
|
||||
const PULSE_DELAY: Duration = Duration::from_secs(3);
|
||||
const PULSE_PERIOD: Duration = Duration::from_millis(100);
|
||||
|
||||
pub struct BufferingPulseController {
|
||||
progress_bar: gtk::ProgressBar,
|
||||
handle: Cell<Option<glib::JoinHandle<()>>>,
|
||||
}
|
||||
|
||||
impl BufferingPulseController {
|
||||
pub fn new(progress_bar: >k::ProgressBar) -> Self {
|
||||
Self {
|
||||
progress_bar: progress_bar.clone(),
|
||||
handle: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self) {
|
||||
let progress_bar = self.progress_bar.clone();
|
||||
|
||||
let prev_handle = self
|
||||
.handle
|
||||
.replace(Some(glib::spawn_future_local(async move {
|
||||
glib::timeout_future(PULSE_DELAY).await;
|
||||
progress_bar.set_visible(true);
|
||||
loop {
|
||||
progress_bar.pulse();
|
||||
glib::timeout_future(PULSE_PERIOD).await;
|
||||
}
|
||||
})));
|
||||
|
||||
if let Some(handle) = prev_handle {
|
||||
handle.abort();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
if let Some(handle) = self.handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
self.progress_bar.set_visible(false);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BufferingPulseController {
|
||||
fn drop(&mut self) {
|
||||
if let Some(handle) = self.handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue