feat: add buffer size option

This commit is contained in:
talwat 2025-03-17 16:32:06 +01:00
parent 968c1ee670
commit 34577efe8f
6 changed files with 28 additions and 17 deletions

2
Cargo.lock generated
View File

@ -1453,7 +1453,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "lowfi"
version = "1.6.3-dev"
version = "1.6.4-dev"
dependencies = [
"Inflector",
"arc-swap",

View File

@ -1,6 +1,6 @@
[package]
name = "lowfi"
version = "1.6.3-dev"
version = "1.6.4-dev"
edition = "2021"
description = "An extremely simple lofi player."
license = "MIT"

View File

@ -12,7 +12,7 @@ mod tracks;
mod scrape;
/// An extremely simple lofi player.
#[derive(Parser)]
#[derive(Parser, Clone)]
#[command(about, version)]
#[allow(
clippy::struct_excessive_bools,
@ -45,7 +45,11 @@ struct Args {
/// Use a custom track list
#[clap(long, short, alias = "list", short_alias = 'l')]
tracklist: Option<String>,
track_list: Option<String>,
/// Song buffer size.
#[clap(long, short = 's', alias = "buffer", default_value_t = 5)]
buffer_size: usize,
/// The command that was ran.
/// This is [None] if no command was specified.
@ -54,7 +58,7 @@ struct Args {
}
/// Defines all of the extra commands lowfi can run.
#[derive(Subcommand)]
#[derive(Subcommand, Clone)]
enum Commands {
/// Scrapes the lofi girl website file server for files.
Scrape {

View File

@ -102,13 +102,13 @@ pub async fn play(args: Args) -> eyre::Result<()> {
// Initialize the UI, as well as the internal communication channel.
let (tx, rx) = mpsc::channel(8);
let ui = task::spawn(ui::start(Arc::clone(&player), tx.clone(), args));
let ui = task::spawn(ui::start(Arc::clone(&player), tx.clone(), args.clone()));
// Sends the player an "init" signal telling it to start playing a song straight away.
tx.send(Messages::Init).await?;
// Actually starts the player.
Player::play(Arc::clone(&player), tx.clone(), rx).await?;
Player::play(Arc::clone(&player), tx.clone(), rx, args.buffer_size).await?;
// Save the volume.txt file for the next session.
PersistentVolume::save(player.sink.volume()).await?;

View File

@ -71,9 +71,6 @@ pub enum Messages {
/// The time to wait in between errors.
const TIMEOUT: Duration = Duration::from_secs(3);
/// The amount of songs to buffer up.
const BUFFER_SIZE: usize = 5;
/// Main struct responsible for queuing up & playing tracks.
// TODO: Consider refactoring [Player] from being stored in an [Arc], into containing many smaller [Arc]s.
// TODO: In other words, this would change the type from `Arc<Player>` to just `Player`.
@ -178,7 +175,7 @@ impl Player {
let volume = PersistentVolume::load().await?;
// Load the track list.
let list = List::load(args.tracklist.as_ref()).await?;
let list = List::load(args.track_list.as_ref()).await?;
// We should only shut up alsa forcefully on Linux if we really have to.
#[cfg(target_os = "linux")]
@ -207,7 +204,7 @@ impl Player {
.build()?;
let player = Self {
tracks: RwLock::new(VecDeque::with_capacity(5)),
tracks: RwLock::new(VecDeque::with_capacity(args.buffer_size)),
current: ArcSwapOption::new(None),
client,
sink,
@ -294,10 +291,12 @@ impl Player {
/// skip tracks or pause.
///
/// This will also initialize a [Downloader] as well as an MPRIS server if enabled.
/// The [Downloader]s internal buffer size is determined by `buf_size`.
pub async fn play(
player: Arc<Self>,
tx: Sender<Messages>,
mut rx: Receiver<Messages>,
buf_size: usize,
) -> eyre::Result<()> {
// Initialize the mpris player.
//
@ -313,7 +312,7 @@ impl Player {
})?;
// `itx` is used to notify the `Downloader` when it needs to download new tracks.
let downloader = Downloader::new(Arc::clone(&player));
let downloader = Downloader::new(Arc::clone(&player), buf_size);
let (itx, downloader) = downloader.start();
// Start buffering tracks immediately.

View File

@ -8,7 +8,7 @@ use tokio::{
time::sleep,
};
use super::{Player, BUFFER_SIZE, TIMEOUT};
use super::{Player, TIMEOUT};
/// This struct is responsible for downloading tracks in the background.
///
@ -24,6 +24,9 @@ pub struct Downloader {
/// A copy of the internal sender, which can be useful for keeping
/// track of it.
tx: Sender<()>,
/// The size of the internal download buffer.
buf_size: usize,
}
impl Downloader {
@ -37,9 +40,14 @@ impl Downloader {
///
/// This also sends a [`Sender`] which can be used to notify
/// when the downloader needs to begin downloading more tracks.
pub fn new(player: Arc<Player>) -> Self {
pub fn new(player: Arc<Player>, buf_size: usize) -> Self {
let (tx, rx) = mpsc::channel(8);
Self { player, rx, tx }
Self {
player,
rx,
tx,
buf_size,
}
}
/// Actually starts & consumes the [Downloader].
@ -50,7 +58,7 @@ impl Downloader {
// Loop through each update notification.
while self.rx.recv().await == Some(()) {
// For each update notification, we'll push tracks until the buffer is completely full.
while self.player.tracks.read().await.len() < BUFFER_SIZE {
while self.player.tracks.read().await.len() < self.buf_size {
let data = self.player.list.random(&self.player.client).await;
match data {
Ok(track) => self.player.tracks.write().await.push_back(track),