mirror of
https://github.com/talwat/lowfi
synced 2025-12-07 23:47:46 +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.
|
||||
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 {
|
||||
/// Initializes the downloader with a track list.
|
||||
///
|
||||
/// `tx` specifies the [`Sender`] to be notified with [`crate::Message::Loaded`].
|
||||
pub fn init(size: usize, tracks: tracks::List, tx: Sender<crate::Message>) -> Handle {
|
||||
let client = Client::new();
|
||||
pub fn init(
|
||||
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 downloader = Self {
|
||||
@ -66,19 +73,20 @@ impl Downloader {
|
||||
tx,
|
||||
tracks,
|
||||
client,
|
||||
timeout: Duration::from_secs(1),
|
||||
};
|
||||
|
||||
Handle {
|
||||
Ok(Handle {
|
||||
queue: qrx,
|
||||
task: tokio::spawn(downloader.run()),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Actually runs the downloader, consuming it and beginning
|
||||
/// the cycle of downloading tracks and reporting to the
|
||||
/// rest of the program.
|
||||
async fn run(self) -> crate::Result<()> {
|
||||
const ERROR_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
|
||||
loop {
|
||||
let result = self.tracks.random(&self.client, &PROGRESS).await;
|
||||
match result {
|
||||
@ -93,7 +101,7 @@ impl Downloader {
|
||||
Err(error) => {
|
||||
PROGRESS.store(0, atomic::Ordering::Relaxed);
|
||||
if !error.timeout() {
|
||||
tokio::time::sleep(self.timeout).await;
|
||||
tokio::time::sleep(ERROR_TIMEOUT).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ pub struct Args {
|
||||
fps: u8,
|
||||
|
||||
/// Timeout in seconds for music downloads.
|
||||
#[clap(long, default_value_t = 3)]
|
||||
#[clap(long, default_value_t = 16)]
|
||||
timeout: u64,
|
||||
|
||||
/// Include ALSA & other logs.
|
||||
@ -117,10 +117,9 @@ async fn main() -> eyre::Result<()> {
|
||||
}
|
||||
|
||||
let stream = audio::stream()?;
|
||||
let player = Player::init(args, stream.mixer()).await?;
|
||||
let environment = player.environment();
|
||||
let mut player = Player::init(args, stream.mixer()).await?;
|
||||
let result = player.run().await;
|
||||
|
||||
environment.cleanup(result.is_ok())?;
|
||||
player.environment().cleanup(result.is_ok())?;
|
||||
Ok(result?)
|
||||
}
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
#[allow(dead_code, reason = "this code may not be dead depending on features")]
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
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,
|
||||
|
||||
/// When a track is loaded after the caller previously being told to wait.
|
||||
|
||||
@ -117,6 +117,10 @@ impl Player {
|
||||
/// to be driven via `run`.
|
||||
pub async fn init(args: crate::Args, mixer: &rodio::mixer::Mixer) -> crate::Result<Self> {
|
||||
let (tx, rx) = mpsc::channel(8);
|
||||
if args.paused {
|
||||
tx.send(Message::Pause).await?;
|
||||
}
|
||||
|
||||
tx.send(Message::Init).await?;
|
||||
|
||||
let (utx, urx) = broadcast::channel(8);
|
||||
@ -130,7 +134,12 @@ impl Player {
|
||||
|
||||
Ok(Self {
|
||||
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),
|
||||
bookmarks: Bookmarks::load().await?,
|
||||
current: Current::default(),
|
||||
@ -159,10 +168,11 @@ impl Player {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Drive the main message loop. This function consumes the `Player` and
|
||||
/// will return when a `Message::Quit` is received. It handles commands
|
||||
/// Drives the main message loop of the player.
|
||||
///
|
||||
/// This will return when a `Message::Quit` is received. It handles commands
|
||||
/// 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 {
|
||||
match message {
|
||||
Message::Next | Message::Init | Message::Loaded => {
|
||||
@ -175,9 +185,7 @@ impl Player {
|
||||
download::Output::Loading(progress) => {
|
||||
self.set_current(Current::Loading(progress))?;
|
||||
}
|
||||
download::Output::Queued(queued) => {
|
||||
self.play(queued)?;
|
||||
}
|
||||
download::Output::Queued(queued) => self.play(queued)?,
|
||||
}
|
||||
}
|
||||
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.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("unable to convert number")]
|
||||
#[error("unable to convert number: {0}")]
|
||||
Conversion(#[from] std::num::TryFromIntError),
|
||||
|
||||
#[error("unable to write output")]
|
||||
#[error("unable to write output: {0}")]
|
||||
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>),
|
||||
|
||||
#[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>),
|
||||
|
||||
#[cfg(feature = "mpris")]
|
||||
#[error("mpris bus error")]
|
||||
#[error("mpris bus error: {0}")]
|
||||
ZBus(#[from] mpris_server::zbus::Error),
|
||||
|
||||
#[cfg(feature = "mpris")]
|
||||
#[error("mpris fdo (zbus interface) error")]
|
||||
#[error("mpris fdo (zbus interface) error: {0}")]
|
||||
Fdo(#[from] mpris_server::zbus::fdo::Error),
|
||||
}
|
||||
|
||||
|
||||
@ -77,13 +77,6 @@ impl PersistentVolume {
|
||||
pub async fn save(volume: f32) -> Result<()> {
|
||||
let config = Self::config().await?;
|
||||
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;
|
||||
fs::write(path, percentage.to_string()).await?;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user