mirror of
https://github.com/talwat/lowfi
synced 2025-03-20 20:12:20 +00:00
feat: add buffer size option
This commit is contained in:
parent
968c1ee670
commit
34577efe8f
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1453,7 +1453,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lowfi"
|
name = "lowfi"
|
||||||
version = "1.6.3-dev"
|
version = "1.6.4-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lowfi"
|
name = "lowfi"
|
||||||
version = "1.6.3-dev"
|
version = "1.6.4-dev"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "An extremely simple lofi player."
|
description = "An extremely simple lofi player."
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -12,7 +12,7 @@ mod tracks;
|
|||||||
mod scrape;
|
mod scrape;
|
||||||
|
|
||||||
/// An extremely simple lofi player.
|
/// An extremely simple lofi player.
|
||||||
#[derive(Parser)]
|
#[derive(Parser, Clone)]
|
||||||
#[command(about, version)]
|
#[command(about, version)]
|
||||||
#[allow(
|
#[allow(
|
||||||
clippy::struct_excessive_bools,
|
clippy::struct_excessive_bools,
|
||||||
@ -45,7 +45,11 @@ struct Args {
|
|||||||
|
|
||||||
/// Use a custom track list
|
/// Use a custom track list
|
||||||
#[clap(long, short, alias = "list", short_alias = 'l')]
|
#[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.
|
/// The command that was ran.
|
||||||
/// This is [None] if no command was specified.
|
/// This is [None] if no command was specified.
|
||||||
@ -54,7 +58,7 @@ struct Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defines all of the extra commands lowfi can run.
|
/// Defines all of the extra commands lowfi can run.
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand, Clone)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
/// Scrapes the lofi girl website file server for files.
|
/// Scrapes the lofi girl website file server for files.
|
||||||
Scrape {
|
Scrape {
|
||||||
|
@ -102,13 +102,13 @@ pub async fn play(args: Args) -> eyre::Result<()> {
|
|||||||
|
|
||||||
// Initialize the UI, as well as the internal communication channel.
|
// Initialize the UI, as well as the internal communication channel.
|
||||||
let (tx, rx) = mpsc::channel(8);
|
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.
|
// Sends the player an "init" signal telling it to start playing a song straight away.
|
||||||
tx.send(Messages::Init).await?;
|
tx.send(Messages::Init).await?;
|
||||||
|
|
||||||
// Actually starts the player.
|
// 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.
|
// Save the volume.txt file for the next session.
|
||||||
PersistentVolume::save(player.sink.volume()).await?;
|
PersistentVolume::save(player.sink.volume()).await?;
|
||||||
|
@ -71,9 +71,6 @@ pub enum Messages {
|
|||||||
/// The time to wait in between errors.
|
/// The time to wait in between errors.
|
||||||
const TIMEOUT: Duration = Duration::from_secs(3);
|
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.
|
/// 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: 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`.
|
// 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?;
|
let volume = PersistentVolume::load().await?;
|
||||||
|
|
||||||
// Load the track list.
|
// 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.
|
// We should only shut up alsa forcefully on Linux if we really have to.
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@ -207,7 +204,7 @@ impl Player {
|
|||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let player = Self {
|
let player = Self {
|
||||||
tracks: RwLock::new(VecDeque::with_capacity(5)),
|
tracks: RwLock::new(VecDeque::with_capacity(args.buffer_size)),
|
||||||
current: ArcSwapOption::new(None),
|
current: ArcSwapOption::new(None),
|
||||||
client,
|
client,
|
||||||
sink,
|
sink,
|
||||||
@ -294,10 +291,12 @@ impl Player {
|
|||||||
/// skip tracks or pause.
|
/// skip tracks or pause.
|
||||||
///
|
///
|
||||||
/// This will also initialize a [Downloader] as well as an MPRIS server if enabled.
|
/// 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(
|
pub async fn play(
|
||||||
player: Arc<Self>,
|
player: Arc<Self>,
|
||||||
tx: Sender<Messages>,
|
tx: Sender<Messages>,
|
||||||
mut rx: Receiver<Messages>,
|
mut rx: Receiver<Messages>,
|
||||||
|
buf_size: usize,
|
||||||
) -> eyre::Result<()> {
|
) -> eyre::Result<()> {
|
||||||
// Initialize the mpris player.
|
// Initialize the mpris player.
|
||||||
//
|
//
|
||||||
@ -313,7 +312,7 @@ impl Player {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// `itx` is used to notify the `Downloader` when it needs to download new tracks.
|
// `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();
|
let (itx, downloader) = downloader.start();
|
||||||
|
|
||||||
// Start buffering tracks immediately.
|
// Start buffering tracks immediately.
|
||||||
|
@ -8,7 +8,7 @@ use tokio::{
|
|||||||
time::sleep,
|
time::sleep,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Player, BUFFER_SIZE, TIMEOUT};
|
use super::{Player, TIMEOUT};
|
||||||
|
|
||||||
/// This struct is responsible for downloading tracks in the background.
|
/// 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
|
/// A copy of the internal sender, which can be useful for keeping
|
||||||
/// track of it.
|
/// track of it.
|
||||||
tx: Sender<()>,
|
tx: Sender<()>,
|
||||||
|
|
||||||
|
/// The size of the internal download buffer.
|
||||||
|
buf_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Downloader {
|
impl Downloader {
|
||||||
@ -37,9 +40,14 @@ impl Downloader {
|
|||||||
///
|
///
|
||||||
/// This also sends a [`Sender`] which can be used to notify
|
/// This also sends a [`Sender`] which can be used to notify
|
||||||
/// when the downloader needs to begin downloading more tracks.
|
/// 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);
|
let (tx, rx) = mpsc::channel(8);
|
||||||
Self { player, rx, tx }
|
Self {
|
||||||
|
player,
|
||||||
|
rx,
|
||||||
|
tx,
|
||||||
|
buf_size,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actually starts & consumes the [Downloader].
|
/// Actually starts & consumes the [Downloader].
|
||||||
@ -50,7 +58,7 @@ impl Downloader {
|
|||||||
// Loop through each update notification.
|
// Loop through each update notification.
|
||||||
while self.rx.recv().await == Some(()) {
|
while self.rx.recv().await == Some(()) {
|
||||||
// For each update notification, we'll push tracks until the buffer is completely full.
|
// 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;
|
let data = self.player.list.random(&self.player.client).await;
|
||||||
match data {
|
match data {
|
||||||
Ok(track) => self.player.tracks.write().await.push_back(track),
|
Ok(track) => self.player.tracks.write().await.push_back(track),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user