mirror of
https://github.com/talwat/lowfi
synced 2025-12-07 23:47:46 +00:00
fix: error reporting
docs: fix typos
This commit is contained in:
parent
a26623f9c0
commit
e44a8b85c4
@ -3,11 +3,13 @@
|
||||
There are a few guidelines outlined here that will make it more likely for your PR to be accepted.
|
||||
Only ones that are less obvious are going to be listed. If you need to ask, it's probably a no.
|
||||
|
||||
## 1. No AI
|
||||
## 1. AI
|
||||
|
||||
You can use AI for searching and so on, and if there's something minor and tedious that you'd like
|
||||
the AI to write then that's okay, but if it is noticable that you used AI then it is way too much.
|
||||
If you used AI, you aren't helping any maintainer by submitting your slop, it's just a hassle for them.
|
||||
You can use AI for searching or if there's something minor and tedious (eg. tests) that you'd like
|
||||
to avoid having to do manually.
|
||||
|
||||
With that said, if it is noticeable that you used AI then it is way too much.
|
||||
AI generated PR's do not help maintainers, it's just a hassle and frequently wastes their time.
|
||||
|
||||
## 2. Smaller is better
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Environment Variables
|
||||
|
||||
Lowfi has some more specific options, usually as a result of minor feature requests, which are only documented here.
|
||||
If you have some behaviour you'd like to change, which is quite specific, then see if one of these options suits you.
|
||||
If you have some behavior you'd like to change, which is quite specific, then see if one of these options suits you.
|
||||
|
||||
* `LOWFI_FIXED_MPRIS_NAME` - Limits the number of lowfi instances to one, but ensures the player name is always `lowfi`.
|
||||
* `LOWFI_DISABLE_UI` - Disables the UI.
|
||||
|
||||
2
MUSIC.md
2
MUSIC.md
@ -58,7 +58,7 @@ I'm not making money on any of this, and I think degrading the experience for my
|
||||
fellow nerds who just want to listen to some lowfi without all the crap is not worth it.
|
||||
|
||||
At the end of the day, lowfi has a distinct UserAgent. Should chillhop ever take issue with
|
||||
it's behaviour, banning it is extremely simple. I don't want that to happen, but I
|
||||
it's behavior, banning it is extremely simple. I don't want that to happen, but I
|
||||
understand if it does.
|
||||
|
||||
## Well, *I* Hate the Chillhop Music
|
||||
|
||||
20
README.md
20
README.md
@ -5,24 +5,6 @@ It'll do this as simply as it can: no albums, no ads, just lofi.
|
||||
|
||||

|
||||
|
||||
## The Rewrite
|
||||
|
||||
This branch serves as a rewrite for lowfi. The main focus is to make the code more
|
||||
maintainable. This includes such things as:
|
||||
|
||||
- Replacing `Mutex` & `Arc` with channels, massively improving readability and flow.
|
||||
- More clearly handling tracks in different phases of loading, instead of having
|
||||
a mess of different structs.
|
||||
- Making the UI code cleaner and easier to follow.
|
||||
- Rethinking input & control of the player, especially with MPRIS in mind.
|
||||
- Making track loading simpler and more consistent.
|
||||
|
||||
This is an *internal rewrite*, and the goal is to retain every single feature.
|
||||
If there is a feature present in the original version of lowfi that is not present
|
||||
in the rewrite, then it is a bug and must be implemented.
|
||||
|
||||
Currently, it is in an extremely early and non-functional state.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
As of the 1.7.0 version of lowfi, **all** of the audio files embedded
|
||||
@ -207,7 +189,7 @@ If you are dealing with the 1% using another audio format which is in
|
||||
|
||||
> [!NOTE]
|
||||
> Some nice users, especially [danielwerg](https://github.com/danielwerg),
|
||||
> have aleady made alternative track lists located in the [data](https://github.com/talwat/lowfi/blob/main/data/)
|
||||
> have already made alternative track lists located in the [data](https://github.com/talwat/lowfi/blob/main/data/)
|
||||
> directory of this repo. You can use them with lowfi by using the `--track-list` flag.
|
||||
>
|
||||
> Feel free to contribute your own list with a PR.
|
||||
|
||||
20
src/error.rs
20
src/error.rs
@ -15,39 +15,39 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Errors while loading or saving the persistent volume settings.
|
||||
#[error("unable to load/save the persistent volume: {0}")]
|
||||
#[error("unable to load/save the persistent volume")]
|
||||
PersistentVolume(#[from] volume::Error),
|
||||
|
||||
/// Errors while loading or saving bookmarks.
|
||||
#[error("unable to load/save bookmarks: {0}")]
|
||||
#[error("unable to load/save bookmarks")]
|
||||
Bookmarks(#[from] bookmark::Error),
|
||||
|
||||
/// Network request failures from `reqwest`.
|
||||
#[error("unable to fetch data: {0}")]
|
||||
#[error("unable to fetch data")]
|
||||
Request(#[from] reqwest::Error),
|
||||
|
||||
/// Failure converting to/from a C string (FFI helpers).
|
||||
#[error("C string null error: {0}")]
|
||||
#[error("C string null error")]
|
||||
FfiNull(#[from] std::ffi::NulError),
|
||||
|
||||
/// Errors coming from the audio backend / stream handling.
|
||||
#[error("audio playing error: {0}")]
|
||||
#[error("audio playing error")]
|
||||
Rodio(#[from] rodio::StreamError),
|
||||
|
||||
/// Failure to send an internal `Message` over the mpsc channel.
|
||||
#[error("couldn't send internal message: {0}")]
|
||||
#[error("couldn't send internal message")]
|
||||
Send(#[from] mpsc::error::SendError<crate::Message>),
|
||||
|
||||
/// Failure to enqueue a track into the queue channel.
|
||||
#[error("couldn't add track to the queue: {0}")]
|
||||
#[error("couldn't add track to the queue")]
|
||||
Queue(#[from] mpsc::error::SendError<tracks::Queued>),
|
||||
|
||||
/// Failure to broadcast UI updates.
|
||||
#[error("couldn't update UI state: {0}")]
|
||||
#[error("couldn't update UI state")]
|
||||
Broadcast(#[from] broadcast::error::SendError<ui::Update>),
|
||||
|
||||
/// Generic IO error.
|
||||
#[error("io error: {0}")]
|
||||
#[error("io error")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
/// Data directory was not found or could not be determined.
|
||||
@ -59,7 +59,7 @@ pub enum Error {
|
||||
Download,
|
||||
|
||||
/// Integer parsing errors.
|
||||
#[error("couldn't parse integer: {0}")]
|
||||
#[error("couldn't parse integer")]
|
||||
Parse(#[from] std::num::ParseIntError),
|
||||
|
||||
/// Track subsystem error.
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@ -96,6 +96,14 @@ pub fn data_dir() -> crate::Result<PathBuf> {
|
||||
Ok(dir)
|
||||
}
|
||||
|
||||
async fn player(args: Args, environment: ui::Environment) -> crate::Result<()> {
|
||||
let stream = audio::stream()?;
|
||||
let mut player = Player::init(args, environment, stream.mixer()).await?;
|
||||
player.run().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Program entry point.
|
||||
///
|
||||
/// Parses CLI arguments, initializes the audio stream and player, then
|
||||
@ -116,10 +124,9 @@ async fn main() -> eyre::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let stream = audio::stream()?;
|
||||
let mut player = Player::init(args, stream.mixer()).await?;
|
||||
let result = player.run().await;
|
||||
let environment = ui::Environment::ready(args.alternate)?;
|
||||
let result = player(args, environment).await;
|
||||
environment.cleanup(result.is_ok())?;
|
||||
|
||||
player.environment().cleanup(result.is_ok())?;
|
||||
Ok(result?)
|
||||
}
|
||||
|
||||
@ -115,7 +115,11 @@ impl Player {
|
||||
/// This sets up the audio sink, UI, downloader, bookmarks and persistent
|
||||
/// volume state. The function returns a fully constructed `Player` ready
|
||||
/// 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,
|
||||
environment: ui::Environment,
|
||||
mixer: &rodio::mixer::Mixer,
|
||||
) -> crate::Result<Self> {
|
||||
let (tx, rx) = mpsc::channel(8);
|
||||
if args.paused {
|
||||
tx.send(Message::Pause).await?;
|
||||
@ -133,7 +137,7 @@ impl Player {
|
||||
sink.set_volume(volume.float());
|
||||
|
||||
Ok(Self {
|
||||
ui: ui::Handle::init(tx.clone(), urx, state, &args).await?,
|
||||
ui: ui::Handle::init(tx.clone(), environment, urx, state, &args).await?,
|
||||
downloader: Downloader::init(
|
||||
args.buffer_size as usize,
|
||||
args.timeout,
|
||||
|
||||
48
src/ui.rs
48
src/ui.rs
@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
player::Current,
|
||||
@ -39,6 +39,9 @@ pub enum Error {
|
||||
#[error("sharing state between backend and frontend failed: {0}")]
|
||||
Send(#[from] tokio::sync::broadcast::error::SendError<Update>),
|
||||
|
||||
#[error("you can't disable the UI without MPRIS!")]
|
||||
RejectedDisable,
|
||||
|
||||
#[cfg(feature = "mpris")]
|
||||
#[error("mpris bus error: {0}")]
|
||||
ZBus(#[from] mpris_server::zbus::Error),
|
||||
@ -115,6 +118,27 @@ struct Tasks {
|
||||
input: JoinHandle<Result<()>>,
|
||||
}
|
||||
|
||||
impl Tasks {
|
||||
pub fn spawn(
|
||||
tx: Sender<crate::Message>,
|
||||
updater: broadcast::Receiver<ui::Update>,
|
||||
state: State,
|
||||
params: interface::Params,
|
||||
) -> Self {
|
||||
Self {
|
||||
render: tokio::spawn(Handle::ui(updater, state, params)),
|
||||
input: tokio::spawn(input::listen(tx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Tasks {
|
||||
fn drop(&mut self) {
|
||||
self.input.abort();
|
||||
self.render.abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// The UI handle for controlling the state of the UI, as well as
|
||||
/// updating MPRIS information and other small interfacing tasks.
|
||||
pub struct Handle {
|
||||
@ -126,14 +150,7 @@ pub struct Handle {
|
||||
pub mpris: mpris::Server,
|
||||
|
||||
/// The UI's running tasks.
|
||||
tasks: Tasks,
|
||||
}
|
||||
|
||||
impl Drop for Handle {
|
||||
fn drop(&mut self) {
|
||||
self.tasks.input.abort();
|
||||
self.tasks.render.abort();
|
||||
}
|
||||
_tasks: Option<Tasks>,
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
@ -174,19 +191,22 @@ impl Handle {
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn init(
|
||||
tx: Sender<crate::Message>,
|
||||
environment: Environment,
|
||||
updater: broadcast::Receiver<ui::Update>,
|
||||
state: State,
|
||||
args: &Args,
|
||||
) -> Result<Self> {
|
||||
let environment = Environment::ready(args.alternate)?;
|
||||
let disabled = env::var("LOWFI_DISABLE_UI").is_ok_and(|x| x == "1");
|
||||
if disabled && !cfg!(feature = "mpris") {
|
||||
return Err(Error::RejectedDisable);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
#[cfg(feature = "mpris")]
|
||||
mpris: mpris::Server::new(state.clone(), tx.clone(), updater.resubscribe()).await?,
|
||||
environment,
|
||||
tasks: Tasks {
|
||||
render: tokio::spawn(Self::ui(updater, state, interface::Params::from(args))),
|
||||
input: tokio::spawn(input::listen(tx)),
|
||||
},
|
||||
_tasks: (!disabled)
|
||||
.then(|| Tasks::spawn(tx, updater, state, interface::Params::from(args))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ impl PlayerInterface for Player {
|
||||
}
|
||||
|
||||
async fn stop(&self) -> fdo::Result<()> {
|
||||
self.pause().await
|
||||
self.sender.send(Message::Quit).await
|
||||
}
|
||||
|
||||
async fn play(&self) -> fdo::Result<()> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user