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 mpv;
|
||||||
|
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
fn init_tracing() {
|
fn init_tracing() {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use crate::model::Song;
|
use crate::model::Song;
|
||||||
|
use crate::util::buffering::BufferingPulseController;
|
||||||
use crate::{mpris, mpv};
|
use crate::{mpris, mpv};
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
use glib::subclass::InitializingObject;
|
use glib::subclass::InitializingObject;
|
||||||
use glib::JoinHandle;
|
use glib::JoinHandle;
|
||||||
use gtk::{gdk, gio, glib};
|
use gtk::{gdk, gio, glib};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, OnceCell, RefCell};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use tracing::{event, span, Level};
|
use tracing::{event, span, Level};
|
||||||
use zbus::object_server::InterfaceRef;
|
use zbus::object_server::InterfaceRef;
|
||||||
|
@ -78,7 +79,8 @@ mod imp {
|
||||||
|
|
||||||
loading_cover_handle: RefCell<Option<JoinHandle<()>>>,
|
loading_cover_handle: RefCell<Option<JoinHandle<()>>>,
|
||||||
|
|
||||||
buffering_timeout: Cell<Option<glib::SourceId>>,
|
playbar_buffering: OnceCell<BufferingPulseController>,
|
||||||
|
|
||||||
time_pos_notify_timeout: Cell<Option<glib::SourceId>>,
|
time_pos_notify_timeout: Cell<Option<glib::SourceId>>,
|
||||||
|
|
||||||
mpris_player: RefCell<Option<InterfaceRef<mpris::Player>>>,
|
mpris_player: RefCell<Option<InterfaceRef<mpris::Player>>>,
|
||||||
|
@ -140,7 +142,8 @@ mod imp {
|
||||||
|
|
||||||
loading_cover_handle: Default::default(),
|
loading_cover_handle: Default::default(),
|
||||||
|
|
||||||
buffering_timeout: Default::default(),
|
playbar_buffering: Default::default(),
|
||||||
|
|
||||||
time_pos_notify_timeout: Default::default(),
|
time_pos_notify_timeout: Default::default(),
|
||||||
|
|
||||||
mpris_player: Default::default(),
|
mpris_player: Default::default(),
|
||||||
|
@ -539,33 +542,9 @@ mod imp {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffering_start(&self) {
|
fn playbar_buffering(&self) -> &BufferingPulseController {
|
||||||
let started_buffering = std::time::Instant::now();
|
self.playbar_buffering
|
||||||
let window = self.obj().downgrade();
|
.get_or_init(|| BufferingPulseController::new(&self.playbar.pulse_bar()))
|
||||||
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 on_property_change(&self, event: crate::mpv::event::PropertyEvent) {
|
fn on_property_change(&self, event: crate::mpv::event::PropertyEvent) {
|
||||||
|
@ -734,7 +713,7 @@ mod imp {
|
||||||
|
|
||||||
event!(target: "audrey::playback", Level::DEBUG, "StartFile");
|
event!(target: "audrey::playback", Level::DEBUG, "StartFile");
|
||||||
self.obj().notify("song");
|
self.obj().notify("song");
|
||||||
self.buffering_start();
|
self.playbar_buffering().start();
|
||||||
|
|
||||||
let song = self.obj().song().unwrap();
|
let song = self.obj().song().unwrap();
|
||||||
|
|
||||||
|
@ -879,7 +858,7 @@ mod imp {
|
||||||
self.state.set(State::Seeking);
|
self.state.set(State::Seeking);
|
||||||
|
|
||||||
self.obj().notify("time-pos");
|
self.obj().notify("time-pos");
|
||||||
self.buffering_start();
|
self.playbar_buffering().stop();
|
||||||
|
|
||||||
let time_pos = self.obj().time_pos();
|
let time_pos = self.obj().time_pos();
|
||||||
if let Some(iface_ref) = self.mpris_player() {
|
if let Some(iface_ref) = self.mpris_player() {
|
||||||
|
@ -910,7 +889,7 @@ mod imp {
|
||||||
self.state.set(State::Active);
|
self.state.set(State::Active);
|
||||||
|
|
||||||
event!(target: "audrey::playback", Level::DEBUG, "PlaybackRestart");
|
event!(target: "audrey::playback", Level::DEBUG, "PlaybackRestart");
|
||||||
self.buffering_end();
|
self.playbar_buffering().stop();
|
||||||
|
|
||||||
if let Some(queued_seek) = self.queued_seek.take() {
|
if let Some(queued_seek) = self.queued_seek.take() {
|
||||||
// a seek was tried before and failed, try again now
|
// a seek was tried before and failed, try again now
|
||||||
|
@ -943,7 +922,7 @@ mod imp {
|
||||||
self.obj().notify("time-pos");
|
self.obj().notify("time-pos");
|
||||||
|
|
||||||
self.obj().notify("song");
|
self.obj().notify("song");
|
||||||
self.buffering_end();
|
self.playbar_buffering().stop();
|
||||||
|
|
||||||
if let Err(err) = event.reason {
|
if let Err(err) = event.reason {
|
||||||
event!(Level::ERROR, "end file error: {err}");
|
event!(Level::ERROR, "end file error: {err}");
|
||||||
|
@ -964,9 +943,6 @@ mod imp {
|
||||||
if let Some(source) = self.time_pos_notify_timeout.take() {
|
if let Some(source) = self.time_pos_notify_timeout.take() {
|
||||||
source.remove();
|
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