mirror of
https://github.com/talwat/lowfi
synced 2025-12-09 16:34:12 +00:00
fix: make the paused flag function properly
This commit is contained in:
parent
f88b46ec56
commit
cba68de6ff
@ -46,19 +46,26 @@ pub struct Downloader {
|
|||||||
|
|
||||||
/// The [`reqwest`] client to use for downloads.
|
/// The [`reqwest`] client to use for downloads.
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
||||||
/// The timeout to use for both the client,
|
|
||||||
/// and also how long to wait between trying
|
|
||||||
/// again after a failed download.
|
|
||||||
timeout: Duration,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Downloader {
|
impl Downloader {
|
||||||
/// Initializes the downloader with a track list.
|
/// Initializes the downloader with a track list.
|
||||||
///
|
///
|
||||||
/// `tx` specifies the [`Sender`] to be notified with [`crate::Message::Loaded`].
|
/// `tx` specifies the [`Sender`] to be notified with [`crate::Message::Loaded`].
|
||||||
pub fn init(size: usize, tracks: tracks::List, tx: Sender<crate::Message>) -> Handle {
|
pub fn init(
|
||||||
let client = Client::new();
|
size: usize,
|
||||||
|
timeout: u64,
|
||||||
|
tracks: tracks::List,
|
||||||
|
tx: Sender<crate::Message>,
|
||||||
|
) -> crate::Result<Handle> {
|
||||||
|
let client = Client::builder()
|
||||||
|
.user_agent(concat!(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
"/",
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
))
|
||||||
|
.timeout(Duration::from_secs(timeout))
|
||||||
|
.build()?;
|
||||||
|
|
||||||
let (qtx, qrx) = mpsc::channel(size - 1);
|
let (qtx, qrx) = mpsc::channel(size - 1);
|
||||||
let downloader = Self {
|
let downloader = Self {
|
||||||
@ -66,19 +73,20 @@ impl Downloader {
|
|||||||
tx,
|
tx,
|
||||||
tracks,
|
tracks,
|
||||||
client,
|
client,
|
||||||
timeout: Duration::from_secs(1),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Handle {
|
Ok(Handle {
|
||||||
queue: qrx,
|
queue: qrx,
|
||||||
task: tokio::spawn(downloader.run()),
|
task: tokio::spawn(downloader.run()),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actually runs the downloader, consuming it and beginning
|
/// Actually runs the downloader, consuming it and beginning
|
||||||
/// the cycle of downloading tracks and reporting to the
|
/// the cycle of downloading tracks and reporting to the
|
||||||
/// rest of the program.
|
/// rest of the program.
|
||||||
async fn run(self) -> crate::Result<()> {
|
async fn run(self) -> crate::Result<()> {
|
||||||
|
const ERROR_TIMEOUT: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let result = self.tracks.random(&self.client, &PROGRESS).await;
|
let result = self.tracks.random(&self.client, &PROGRESS).await;
|
||||||
match result {
|
match result {
|
||||||
@ -93,7 +101,7 @@ impl Downloader {
|
|||||||
Err(error) => {
|
Err(error) => {
|
||||||
PROGRESS.store(0, atomic::Ordering::Relaxed);
|
PROGRESS.store(0, atomic::Ordering::Relaxed);
|
||||||
if !error.timeout() {
|
if !error.timeout() {
|
||||||
tokio::time::sleep(self.timeout).await;
|
tokio::time::sleep(ERROR_TIMEOUT).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ pub struct Args {
|
|||||||
fps: u8,
|
fps: u8,
|
||||||
|
|
||||||
/// Timeout in seconds for music downloads.
|
/// Timeout in seconds for music downloads.
|
||||||
#[clap(long, default_value_t = 3)]
|
#[clap(long, default_value_t = 16)]
|
||||||
timeout: u64,
|
timeout: u64,
|
||||||
|
|
||||||
/// Include ALSA & other logs.
|
/// Include ALSA & other logs.
|
||||||
@ -117,10 +117,9 @@ async fn main() -> eyre::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let stream = audio::stream()?;
|
let stream = audio::stream()?;
|
||||||
let player = Player::init(args, stream.mixer()).await?;
|
let mut player = Player::init(args, stream.mixer()).await?;
|
||||||
let environment = player.environment();
|
|
||||||
let result = player.run().await;
|
let result = player.run().await;
|
||||||
|
|
||||||
environment.cleanup(result.is_ok())?;
|
player.environment().cleanup(result.is_ok())?;
|
||||||
Ok(result?)
|
Ok(result?)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
#[allow(dead_code, reason = "this code may not be dead depending on features")]
|
#[allow(dead_code, reason = "this code may not be dead depending on features")]
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
/// Deliberate user request to go to the next song.
|
/// Deliberate user request to go to the next song, also sent when the
|
||||||
|
/// song is over by the waiter.
|
||||||
Next,
|
Next,
|
||||||
|
|
||||||
/// When a track is loaded after the caller previously being told to wait.
|
/// When a track is loaded after the caller previously being told to wait.
|
||||||
|
|||||||
@ -117,6 +117,10 @@ impl Player {
|
|||||||
/// to be driven via `run`.
|
/// to be driven via `run`.
|
||||||
pub async fn init(args: crate::Args, mixer: &rodio::mixer::Mixer) -> crate::Result<Self> {
|
pub async fn init(args: crate::Args, mixer: &rodio::mixer::Mixer) -> crate::Result<Self> {
|
||||||
let (tx, rx) = mpsc::channel(8);
|
let (tx, rx) = mpsc::channel(8);
|
||||||
|
if args.paused {
|
||||||
|
tx.send(Message::Pause).await?;
|
||||||
|
}
|
||||||
|
|
||||||
tx.send(Message::Init).await?;
|
tx.send(Message::Init).await?;
|
||||||
|
|
||||||
let (utx, urx) = broadcast::channel(8);
|
let (utx, urx) = broadcast::channel(8);
|
||||||
@ -130,7 +134,12 @@ impl Player {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ui: ui::Handle::init(tx.clone(), urx, state, &args).await?,
|
ui: ui::Handle::init(tx.clone(), urx, state, &args).await?,
|
||||||
downloader: Downloader::init(args.buffer_size as usize, list, tx.clone()),
|
downloader: Downloader::init(
|
||||||
|
args.buffer_size as usize,
|
||||||
|
args.timeout,
|
||||||
|
list,
|
||||||
|
tx.clone(),
|
||||||
|
)?,
|
||||||
waiter: waiter::Handle::new(Arc::clone(&sink), tx),
|
waiter: waiter::Handle::new(Arc::clone(&sink), tx),
|
||||||
bookmarks: Bookmarks::load().await?,
|
bookmarks: Bookmarks::load().await?,
|
||||||
current: Current::default(),
|
current: Current::default(),
|
||||||
@ -159,10 +168,11 @@ impl Player {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drive the main message loop. This function consumes the `Player` and
|
/// Drives the main message loop of the player.
|
||||||
/// will return when a `Message::Quit` is received. It handles commands
|
///
|
||||||
|
/// This will return when a `Message::Quit` is received. It handles commands
|
||||||
/// coming from the frontend and updates playback/UI state accordingly.
|
/// coming from the frontend and updates playback/UI state accordingly.
|
||||||
pub async fn run(mut self) -> crate::Result<()> {
|
pub async fn run(&mut self) -> crate::Result<()> {
|
||||||
while let Some(message) = self.rx.recv().await {
|
while let Some(message) = self.rx.recv().await {
|
||||||
match message {
|
match message {
|
||||||
Message::Next | Message::Init | Message::Loaded => {
|
Message::Next | Message::Init | Message::Loaded => {
|
||||||
@ -175,9 +185,7 @@ impl Player {
|
|||||||
download::Output::Loading(progress) => {
|
download::Output::Loading(progress) => {
|
||||||
self.set_current(Current::Loading(progress))?;
|
self.set_current(Current::Loading(progress))?;
|
||||||
}
|
}
|
||||||
download::Output::Queued(queued) => {
|
download::Output::Queued(queued) => self.play(queued)?,
|
||||||
self.play(queued)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Play => {
|
Message::Play => {
|
||||||
|
|||||||
12
src/ui.rs
12
src/ui.rs
@ -27,24 +27,24 @@ type Result<T> = std::result::Result<T, Error>;
|
|||||||
/// that occur while drawing the UI or handling input.
|
/// that occur while drawing the UI or handling input.
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("unable to convert number")]
|
#[error("unable to convert number: {0}")]
|
||||||
Conversion(#[from] std::num::TryFromIntError),
|
Conversion(#[from] std::num::TryFromIntError),
|
||||||
|
|
||||||
#[error("unable to write output")]
|
#[error("unable to write output: {0}")]
|
||||||
Write(#[from] std::io::Error),
|
Write(#[from] std::io::Error),
|
||||||
|
|
||||||
#[error("sending message to backend from ui failed")]
|
#[error("sending message to backend from ui failed: {0}")]
|
||||||
CrateSend(#[from] tokio::sync::mpsc::error::SendError<crate::Message>),
|
CrateSend(#[from] tokio::sync::mpsc::error::SendError<crate::Message>),
|
||||||
|
|
||||||
#[error("sharing state between backend and frontend failed")]
|
#[error("sharing state between backend and frontend failed: {0}")]
|
||||||
Send(#[from] tokio::sync::broadcast::error::SendError<Update>),
|
Send(#[from] tokio::sync::broadcast::error::SendError<Update>),
|
||||||
|
|
||||||
#[cfg(feature = "mpris")]
|
#[cfg(feature = "mpris")]
|
||||||
#[error("mpris bus error")]
|
#[error("mpris bus error: {0}")]
|
||||||
ZBus(#[from] mpris_server::zbus::Error),
|
ZBus(#[from] mpris_server::zbus::Error),
|
||||||
|
|
||||||
#[cfg(feature = "mpris")]
|
#[cfg(feature = "mpris")]
|
||||||
#[error("mpris fdo (zbus interface) error")]
|
#[error("mpris fdo (zbus interface) error: {0}")]
|
||||||
Fdo(#[from] mpris_server::zbus::fdo::Error),
|
Fdo(#[from] mpris_server::zbus::fdo::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,13 +77,6 @@ impl PersistentVolume {
|
|||||||
pub async fn save(volume: f32) -> Result<()> {
|
pub async fn save(volume: f32) -> Result<()> {
|
||||||
let config = Self::config().await?;
|
let config = Self::config().await?;
|
||||||
let path = config.join(PathBuf::from("volume.txt"));
|
let path = config.join(PathBuf::from("volume.txt"));
|
||||||
|
|
||||||
// Already rounded & absolute, therefore this should be safe.
|
|
||||||
#[expect(
|
|
||||||
clippy::as_conversions,
|
|
||||||
clippy::cast_sign_loss,
|
|
||||||
clippy::cast_possible_truncation
|
|
||||||
)]
|
|
||||||
let percentage = (volume * 100.0).abs().round() as u16;
|
let percentage = (volume * 100.0).abs().round() as u16;
|
||||||
fs::write(path, percentage.to_string()).await?;
|
fs::write(path, percentage.to_string()).await?;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user