use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
pub struct SharedState {
active: AtomicBool,
paused: AtomicBool,
samples_played: AtomicU64,
track_ended: AtomicBool,
seek_pending: AtomicBool,
seek_generation: AtomicU64,
duration_micros: AtomicU64,
}
impl Default for SharedState {
fn default() -> Self {
SharedState {
active: AtomicBool::new(false),
paused: AtomicBool::new(false),
samples_played: AtomicU64::new(0),
track_ended: AtomicBool::new(false),
seek_pending: AtomicBool::new(false),
seek_generation: AtomicU64::new(0),
duration_micros: AtomicU64::new(0),
}
}
}
impl SharedState {
pub(crate) fn is_active(&self) -> bool {
self.active.load(Ordering::Acquire)
}
pub(crate) fn is_paused(&self) -> bool {
self.paused.load(Ordering::Relaxed)
}
pub(crate) fn get_samples(&self) -> u64 {
self.samples_played.load(Ordering::Acquire)
}
pub(crate) fn is_seeking(&self) -> bool {
self.seek_pending.load(Ordering::Acquire)
}
pub(crate) fn seek_generation(&self) -> u64 {
self.seek_generation.load(Ordering::Acquire)
}
pub(crate) fn get_duration_secs(&self) -> f64 {
self.duration_micros.load(Ordering::Acquire) as f64 / 1_000_000.0
}
pub(crate) fn set_active(&self, val: bool) {
self.active.store(val, Ordering::Release);
}
pub(crate) fn set_paused(&self, val: bool) {
if val && !self.is_active() {
return;
}
self.paused.store(val, Ordering::Relaxed);
}
pub(crate) fn toggle_playback(&self) {
if self.is_active() {
self.paused.fetch_xor(true, Ordering::Relaxed);
} else {
self.paused.store(false, Ordering::Relaxed)
}
}
pub(crate) fn set_samples(&self, samples: u64) {
self.samples_played.store(samples, Ordering::SeqCst);
}
pub(crate) fn add_samples(&self, val: u64) {
self.samples_played.fetch_add(val, Ordering::Release);
}
pub(crate) fn reset_samples(&self) {
self.samples_played.store(0, Ordering::Release);
}
pub(crate) fn set_duration_secs(&self, secs: f64) {
let micros = (secs * 1_000_000.0) as u64;
self.duration_micros.store(micros, Ordering::Release);
}
pub(crate) fn signal_track_ended(&self) {
self.track_ended.store(true, Ordering::Release);
}
pub(crate) fn take_track_ended(&self) -> bool {
self.track_ended.swap(false, Ordering::Acquire)
}
pub(crate) fn start_seek(&self) {
self.seek_pending.store(true, Ordering::Release);
self.seek_generation.fetch_add(1, Ordering::Release);
}
pub(crate) fn finish_seek(&self) {
self.seek_pending.store(false, Ordering::Release);
}
}