feat: remember volume

This commit is contained in:
Tal 2024-10-06 18:52:11 +02:00
parent 901bf0e871
commit 6b157dd457
4 changed files with 196 additions and 5 deletions

115
Cargo.lock generated
View File

@ -658,6 +658,27 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "dtoa" name = "dtoa"
version = "1.0.9" version = "1.0.9"
@ -1257,6 +1278,16 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"libc",
]
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.14" version = "0.4.14"
@ -1288,6 +1319,7 @@ dependencies = [
"bytes", "bytes",
"clap", "clap",
"crossterm", "crossterm",
"dirs",
"eyre", "eyre",
"futures", "futures",
"lazy_static", "lazy_static",
@ -1589,6 +1621,12 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "ordered-stream" name = "ordered-stream"
version = "0.2.0" version = "0.2.0"
@ -1849,6 +1887,17 @@ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
] ]
[[package]]
name = "redox_users"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.0" version = "1.11.0"
@ -2864,6 +2913,15 @@ dependencies = [
"windows-targets 0.42.2", "windows-targets 0.42.2",
] ]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"
@ -2897,6 +2955,21 @@ dependencies = [
"windows_x86_64_msvc 0.42.2", "windows_x86_64_msvc 0.42.2",
] ]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"
@ -2919,6 +2992,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.6" version = "0.52.6"
@ -2931,6 +3010,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.6" version = "0.52.6"
@ -2943,6 +3028,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.6" version = "0.52.6"
@ -2961,6 +3052,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.6" version = "0.52.6"
@ -2973,6 +3070,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.6" version = "0.52.6"
@ -2985,6 +3088,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.6" version = "0.52.6"
@ -2997,6 +3106,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.6"

View File

@ -29,6 +29,7 @@ rand = "0.8.5"
tokio = { version = "1.40.0", features = [ tokio = { version = "1.40.0", features = [
"macros", "macros",
"rt-multi-thread", "rt-multi-thread",
"fs"
], default-features = false } ], default-features = false }
futures = "0.3.30" futures = "0.3.30"
arc-swap = "1.7.1" arc-swap = "1.7.1"
@ -37,11 +38,14 @@ arc-swap = "1.7.1"
reqwest = "0.12.7" reqwest = "0.12.7"
bytes = "1.7.2" bytes = "1.7.2"
# I/O
crossterm = { version = "0.28.1", features = ["event-stream"] }
rodio = { version = "0.19.0", features = ["symphonia-mp3"], default-features = false }
mpris-server = { version = "0.8.1", optional = true }
dirs = "5.0.1"
# Misc # Misc
scraper = "0.20.0" scraper = "0.20.0"
rodio = { version = "0.19.0", features = ["symphonia-mp3"], default-features = false }
crossterm = { version = "0.28.1", features = ["event-stream"] }
Inflector = "0.11.4" Inflector = "0.11.4"
lazy_static = "1.5.0" lazy_static = "1.5.0"
libc = "0.2.159" libc = "0.2.159"
mpris-server = { version = "0.8.1", optional = true }

View File

@ -1,23 +1,88 @@
//! Responsible for the basic initialization & shutdown of the audio server & frontend. //! Responsible for the basic initialization & shutdown of the audio server & frontend.
use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use eyre::eyre;
use tokio::fs;
use tokio::{sync::mpsc, task}; use tokio::{sync::mpsc, task};
use crate::player::Player; use crate::player::Player;
use crate::player::{ui, Messages}; use crate::player::{ui, Messages};
use crate::Args; use crate::Args;
/// The attributes that are applied at startup.
/// This includes the volume, but also the config file.
///
/// The volume is seperated from the config since it specifically
/// will be written by lowfi, whereas the config will not.
pub struct InitialProperties {
/// The volume, as a percentage.
pub volume: u16,
}
impl InitialProperties {
/// Retrieves the config directory.
async fn config() -> eyre::Result<PathBuf> {
let config = dirs::config_dir()
.ok_or(eyre!("Couldn't find config directory"))?
.join(PathBuf::from("lowfi"));
if !config.exists() {
fs::create_dir_all(&config).await?;
}
Ok(config)
}
/// Loads the [InitialProperties], including the config and volume file.
pub async fn load() -> eyre::Result<Self> {
let config = Self::config().await?;
let volume = config.join(PathBuf::from("volume.txt"));
// Basically just read from the volume file if it exists, otherwise return 100.
let volume = if volume.exists() {
let contents = fs::read_to_string(volume).await?;
let stripped = contents.strip_suffix("%").unwrap_or(&contents);
stripped
.parse()
.map_err(|_| eyre!("volume.txt file is invalid"))?
} else {
fs::write(&volume, "100").await?;
100u16
};
Ok(InitialProperties { volume })
}
/// Saves `volume.txt`, and uses the home directory which was previously acquired.
pub async fn save_volume(volume: f32) -> eyre::Result<()> {
let config = Self::config().await?;
let path = config.join(PathBuf::from("volume.txt"));
fs::write(path, ((volume * 100.0).abs().round() as u16).to_string()).await?;
Ok(())
}
}
/// Initializes the audio server, and then safely stops /// Initializes the audio server, and then safely stops
/// it when the frontend quits. /// it when the frontend quits.
pub async fn play(args: Args) -> eyre::Result<()> { pub async fn play(args: Args) -> eyre::Result<()> {
// Load the initial properties (volume & config).
let properties = InitialProperties::load().await?;
let (tx, rx) = mpsc::channel(8); let (tx, rx) = mpsc::channel(8);
let player = Arc::new(Player::new(!args.alternate).await?); let player = Arc::new(Player::new(!args.alternate).await?);
let ui = task::spawn(ui::start(Arc::clone(&player), tx.clone(), args)); let ui = task::spawn(ui::start(Arc::clone(&player), tx.clone(), args));
tx.send(Messages::Init).await?; tx.send(Messages::Init).await?;
Player::play(Arc::clone(&player), tx.clone(), rx).await?; Player::play(Arc::clone(&player), properties, tx.clone(), rx).await?;
// Save the volume.txt file for the next session.
InitialProperties::save_volume(player.sink.volume()).await?;
player.sink.stop(); player.sink.stop();
ui.abort(); ui.abort();

View File

@ -18,7 +18,10 @@ use tokio::{
task, task,
}; };
use crate::tracks::{DecodedTrack, Track, TrackInfo}; use crate::{
play::InitialProperties,
tracks::{DecodedTrack, Track, TrackInfo},
};
pub mod downloader; pub mod downloader;
pub mod ui; pub mod ui;
@ -236,6 +239,7 @@ impl Player {
/// skip tracks or pause. /// skip tracks or pause.
pub async fn play( pub async fn play(
player: Arc<Self>, player: Arc<Self>,
properties: InitialProperties,
tx: Sender<Messages>, tx: Sender<Messages>,
mut rx: Receiver<Messages>, mut rx: Receiver<Messages>,
) -> eyre::Result<()> { ) -> eyre::Result<()> {
@ -246,6 +250,9 @@ impl Player {
// Start buffering tracks immediately. // Start buffering tracks immediately.
itx.send(()).await?; itx.send(()).await?;
// Set the initial sink volume to the one specified.
player.sink.set_volume(properties.volume as f32 / 100.0);
loop { loop {
let clone = Arc::clone(&player); let clone = Arc::clone(&player);