mirror of
https://github.com/talwat/lowfi
synced 2026-01-08 23:13:44 +00:00
chore: eliminate public statics
This commit is contained in:
parent
9acfcdcf9d
commit
6f6a552de5
@ -1,3 +1,5 @@
|
||||
//! Some simple audio related utilities.
|
||||
|
||||
pub mod waiter;
|
||||
|
||||
/// This gets the output stream while also shutting up alsa with [libc].
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! All of the logic and state relating to the downloader.
|
||||
|
||||
use std::{
|
||||
sync::atomic::{self, AtomicBool, AtomicU8},
|
||||
time::Duration,
|
||||
@ -13,14 +15,40 @@ use tokio::sync::mpsc;
|
||||
/// indicate to the UI that a download is in progress.
|
||||
static LOADING: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// Global download progress in the range 0..=100 updated atomically.
|
||||
/// Global download progress as an integer updated atomically.
|
||||
///
|
||||
/// The UI can read this `AtomicU8` to render a global progress indicator
|
||||
/// when there isn't an immediately queued track available.
|
||||
pub(crate) static PROGRESS: AtomicU8 = AtomicU8::new(0);
|
||||
/// This is just a [`AtomicU8`] from 0 to 255, really representing
|
||||
/// a progress percentage as just a simple integer. For instance,
|
||||
/// 0.5 would be represented here as 127.
|
||||
static PROGRESS: AtomicU8 = AtomicU8::new(0);
|
||||
|
||||
/// A convenient alias for the progress `AtomicU8` pointer type.
|
||||
pub type Progress = &'static AtomicU8;
|
||||
/// A convenient wrapper for the global progress. This is updated by the downloader,
|
||||
/// and then accessed by the UI to display progress when there isn't an available
|
||||
/// queued track.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Progress(&'static AtomicU8);
|
||||
|
||||
impl Progress {
|
||||
/// Creates a new handle to the global progress.
|
||||
pub fn new() -> Self {
|
||||
Self(&PROGRESS)
|
||||
}
|
||||
|
||||
/// Sets the global progress.
|
||||
///
|
||||
/// `value` must be between 0 and 1.
|
||||
pub fn set(&self, value: f32) {
|
||||
self.0.store(
|
||||
(value * f32::from(u8::MAX)).round() as u8,
|
||||
atomic::Ordering::Relaxed,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the global progress as a [`f32`] between 0 and 1.
|
||||
pub fn get(&self) -> f32 {
|
||||
f32::from(self.0.load(atomic::Ordering::Relaxed)) / f32::from(u8::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
/// The downloader, which has all of the state necessary
|
||||
/// to download tracks and add them to the queue.
|
||||
@ -57,7 +85,7 @@ impl Downloader {
|
||||
loop {
|
||||
let result = self
|
||||
.tracks
|
||||
.random(&self.client, &PROGRESS, &mut self.rng)
|
||||
.random(&self.client, Progress::new(), &mut self.rng)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
@ -106,7 +134,7 @@ impl Handle {
|
||||
pub fn track(&mut self) -> Output {
|
||||
self.queue.try_recv().map_or_else(|_| {
|
||||
LOADING.store(true, atomic::Ordering::Relaxed);
|
||||
Output::Loading(Some(&PROGRESS))
|
||||
Output::Loading(Some(Progress::new()))
|
||||
}, Output::Queued,
|
||||
)
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
//! An extremely simple lofi player.
|
||||
|
||||
use crate::player::Player;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod audio;
|
||||
pub mod bookmark;
|
||||
pub mod download;
|
||||
pub mod downloader;
|
||||
pub mod error;
|
||||
pub mod message;
|
||||
pub mod player;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
use std::sync::Arc;
|
||||
//! The player, which contains all of the core logic behind the music player.
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::{self, Receiver};
|
||||
|
||||
use crate::{
|
||||
audio::waiter,
|
||||
bookmark::Bookmarks,
|
||||
download,
|
||||
downloader,
|
||||
tracks::{self, List},
|
||||
ui,
|
||||
volume::PersistentVolume,
|
||||
@ -20,7 +21,7 @@ use crate::{
|
||||
pub enum Current {
|
||||
/// Waiting for a track to arrive. The optional `Progress` is used to
|
||||
/// indicate global download progress when present.
|
||||
Loading(Option<download::Progress>),
|
||||
Loading(Option<downloader::Progress>),
|
||||
|
||||
/// A decoded track that can be played; contains the track `Info`.
|
||||
Track(tracks::Info),
|
||||
@ -52,7 +53,7 @@ pub struct Player {
|
||||
current: Current,
|
||||
|
||||
/// Background downloader that fills the internal queue.
|
||||
downloader: download::Handle,
|
||||
downloader: downloader::Handle,
|
||||
|
||||
/// Receiver for incoming `Message` commands.
|
||||
rx: Receiver<crate::Message>,
|
||||
@ -158,10 +159,10 @@ impl Player {
|
||||
|
||||
self.sink.stop();
|
||||
match self.downloader.track() {
|
||||
download::Output::Loading(progress) => {
|
||||
downloader::Output::Loading(progress) => {
|
||||
self.set_current(Current::Loading(progress))?;
|
||||
}
|
||||
download::Output::Queued(queued) => self.play(queued)?,
|
||||
downloader::Output::Queued(queued) => self.play(queued)?,
|
||||
}
|
||||
}
|
||||
Message::Play => {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
//! Built in web scraping, which isn't guaranteed to have a unified UI.
|
||||
#![allow(clippy::all)]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Task management.
|
||||
//!
|
||||
//! This file aims to abstract a lot of annoying Rust async logic, which may be subject to change.
|
||||
//! For those who are not intimately familiar with async rust, this will be very confusing.
|
||||
//! This file aims to abstract a lot of potentially annoying Rust async logic, which may be
|
||||
//! subject to change.
|
||||
|
||||
use futures_util::TryFutureExt;
|
||||
use std::future::Future;
|
||||
|
||||
@ -108,7 +108,7 @@ mod decoded {
|
||||
|
||||
#[cfg(test)]
|
||||
mod list {
|
||||
use crate::{download::PROGRESS, tracks::List};
|
||||
use crate::{downloader::Progress, tracks::List};
|
||||
use reqwest::Client;
|
||||
|
||||
#[test]
|
||||
@ -172,7 +172,7 @@ mod list {
|
||||
|
||||
let client = Client::new();
|
||||
let track = list
|
||||
.random(&client, &PROGRESS, &mut fastrand::Rng::new())
|
||||
.random(&client, Progress::new(), &mut fastrand::Rng::new())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(track.display, "Apple Juice");
|
||||
|
||||
@ -125,7 +125,7 @@ mod interface {
|
||||
use tokio::time::Instant;
|
||||
|
||||
use crate::{
|
||||
download::PROGRESS,
|
||||
downloader::Progress,
|
||||
player::Current,
|
||||
tracks,
|
||||
ui::{Interface, State},
|
||||
@ -175,9 +175,9 @@ mod interface {
|
||||
#[tokio::test]
|
||||
async fn progress() {
|
||||
let sink = Arc::new(rodio::Sink::new().0);
|
||||
PROGRESS.store(50, std::sync::atomic::Ordering::Relaxed);
|
||||
Progress::new().set(0.5);
|
||||
let mut state = State::initial(sink, String::from("test"));
|
||||
state.current = Current::Loading(Some(&PROGRESS));
|
||||
state.current = Current::Loading(Some(Progress::new()));
|
||||
|
||||
let menu = Interface::default().menu(&mut state);
|
||||
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
//! The module containing all of the logic behind track lists,
|
||||
//! as well as obtaining track names & downloading the raw audio data
|
||||
|
||||
use std::{
|
||||
cmp::min,
|
||||
sync::atomic::{AtomicU8, Ordering},
|
||||
};
|
||||
use std::cmp::min;
|
||||
|
||||
use bytes::{BufMut as _, Bytes, BytesMut};
|
||||
use futures_util::StreamExt as _;
|
||||
@ -13,6 +10,7 @@ use tokio::fs;
|
||||
|
||||
use crate::{
|
||||
data_dir,
|
||||
downloader::Progress,
|
||||
tracks::{
|
||||
self,
|
||||
error::{self, WithTrackContext as _},
|
||||
@ -70,7 +68,7 @@ impl List {
|
||||
&self,
|
||||
track: &str,
|
||||
client: &Client,
|
||||
progress: Option<&AtomicU8>,
|
||||
progress: Option<Progress>,
|
||||
) -> tracks::Result<(Bytes, String)> {
|
||||
// If the track has a protocol, then we should ignore the base for it.
|
||||
let path = if track.contains("://") {
|
||||
@ -114,8 +112,7 @@ impl List {
|
||||
while let Some(item) = stream.next().await {
|
||||
let chunk = item.track(track)?;
|
||||
downloaded = min(downloaded + (chunk.len() as u64), total);
|
||||
let rounded = ((downloaded as f64) / (total as f64) * 100.0).round() as u8;
|
||||
progress.store(rounded, Ordering::Relaxed);
|
||||
progress.set(downloaded as f32 / total as f32);
|
||||
|
||||
bytes.put(chunk);
|
||||
}
|
||||
@ -133,7 +130,7 @@ impl List {
|
||||
pub async fn random(
|
||||
&self,
|
||||
client: &Client,
|
||||
progress: &AtomicU8,
|
||||
progress: Progress,
|
||||
rng: &mut fastrand::Rng,
|
||||
) -> tracks::Result<Queued> {
|
||||
let (path, display) = self.random_path(rng);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Everything which has to do with the user interface, including both input and output.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::player::Current;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Contains the initialization and other handling of the terminal environment.
|
||||
|
||||
use std::{io::stdout, panic};
|
||||
|
||||
use crossterm::{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Responsible for the actual graphical interface of lowfi.
|
||||
|
||||
use crate::{
|
||||
ui::{self, State},
|
||||
Args,
|
||||
|
||||
@ -111,7 +111,7 @@ impl ActionBar {
|
||||
pub fn action(state: &ui::State, width: usize) -> String {
|
||||
let action = match state.current.clone() {
|
||||
Current::Loading(progress) => {
|
||||
ActionBar::Loading(progress.map(|x| x.load(std::sync::atomic::Ordering::Relaxed)))
|
||||
ActionBar::Loading(progress.map(|x| (x.get() * 100.0).round() as u8))
|
||||
}
|
||||
Current::Track(info) => {
|
||||
if state.sink.volume() < 0.01 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user