chore: update dependencies

for some reason, rodio decided it would be a great idea to change all of
the core terminology to be less technical. this is frankly strange, but
it's best not to use an outdated version of the dependency.

rodio is for some reason switching to a "breaking change every single
update" versioning model. why? i have frankly no idea, semver exists for
a reason and they decided just not to use it. 0.x.x is stupid, and
people should realize semver exists for a reason. to the total of zero
people who will read this, thanks for reading my short rant.
This commit is contained in:
Tal 2026-03-05 20:34:45 +01:00
parent 3f39af33e3
commit 02a4e688bd
9 changed files with 582 additions and 294 deletions

832
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "lowfi" name = "lowfi"
version = "2.0.2" version = "2.0.3"
rust-version = "1.83.0" rust-version = "1.83.0"
edition = "2021" edition = "2021"
description = "An extremely simple lofi player." description = "An extremely simple lofi player."
@ -47,7 +47,7 @@ bytes = "1.9.0"
# I/O # I/O
crossterm = { version = "0.29.0", features = ["event-stream", "windows"], default-features = false } crossterm = { version = "0.29.0", features = ["event-stream", "windows"], default-features = false }
rodio = { version = "0.21.1", features = ["symphonia-mp3", "playback"], default-features = false } rodio = { version = "0.22.2", features = ["symphonia-mp3", "playback"], default-features = false }
mpris-server = { version = "0.9.0", optional = true } mpris-server = { version = "0.9.0", optional = true }
dirs = "6.0.0" dirs = "6.0.0"

View File

@ -5,9 +5,9 @@ pub mod waiter;
/// This gets the output stream while also shutting up alsa with [libc]. /// This gets the output stream while also shutting up alsa with [libc].
/// Uses raw libc calls, and therefore is functional only on Linux. /// Uses raw libc calls, and therefore is functional only on Linux.
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn silent_get_output_stream() -> crate::Result<rodio::OutputStream> { fn silent_get_output_stream() -> crate::Result<rodio::MixerDeviceSink> {
use libc::freopen; use libc::freopen;
use rodio::OutputStreamBuilder; use rodio::DeviceSinkBuilder;
use std::ffi::CString; use std::ffi::CString;
// Get the file descriptor to stderr from libc. // Get the file descriptor to stderr from libc.
@ -29,8 +29,8 @@ fn silent_get_output_stream() -> crate::Result<rodio::OutputStream> {
freopen(null.as_ptr(), mode.as_ptr(), stderr); freopen(null.as_ptr(), mode.as_ptr(), stderr);
}; };
// Make the OutputStream while stderr is still redirected to /dev/null. // Make the MixerDeviceSink while stderr is still redirected to /dev/null.
let stream = OutputStreamBuilder::open_default_stream()?; let stream = DeviceSinkBuilder::open_default_sink()?;
// Redirect back to the current terminal, so that other output isn't silenced. // Redirect back to the current terminal, so that other output isn't silenced.
let tty = CString::new("/dev/tty")?; let tty = CString::new("/dev/tty")?;
@ -44,11 +44,11 @@ fn silent_get_output_stream() -> crate::Result<rodio::OutputStream> {
} }
/// Creates an audio stream, doing so silently on Linux. /// Creates an audio stream, doing so silently on Linux.
pub fn stream() -> crate::Result<rodio::OutputStream> { pub fn stream() -> crate::Result<rodio::MixerDeviceSink> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
let mut stream = silent_get_output_stream()?; let mut stream = silent_get_output_stream()?;
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
let mut stream = rodio::OutputStreamBuilder::open_default_stream()?; let mut stream = rodio::DeviceSinkBuilder::open_default_stream()?;
stream.log_on_drop(false); stream.log_on_drop(false);
Ok(stream) Ok(stream)

View File

@ -1,6 +1,5 @@
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use rodio::Sink;
use tokio::{ use tokio::{
sync::{mpsc, Notify}, sync::{mpsc, Notify},
time, time,
@ -9,7 +8,7 @@ use tokio::{
/// Background loop that waits for the sink to drain and then attempts /// Background loop that waits for the sink to drain and then attempts
/// to send a `Message::Next` to the provided channel. /// to send a `Message::Next` to the provided channel.
async fn waiter( async fn waiter(
sink: Arc<Sink>, sink: Arc<rodio::Player>,
tx: mpsc::Sender<crate::Message>, tx: mpsc::Sender<crate::Message>,
notify: Arc<Notify>, notify: Arc<Notify>,
) -> crate::Result<()> { ) -> crate::Result<()> {
@ -44,7 +43,7 @@ impl Handle {
impl crate::Tasks { impl crate::Tasks {
/// Create a new `Handle` which watches the provided `sink` and sends /// Create a new `Handle` which watches the provided `sink` and sends
/// `Message::Next` down `tx` when the sink becomes empty. /// `Message::Next` down `tx` when the sink becomes empty.
pub fn waiter(&mut self, sink: Arc<Sink>) -> Handle { pub fn waiter(&mut self, sink: Arc<rodio::Player>) -> Handle {
let notify = Arc::new(Notify::new()); let notify = Arc::new(Notify::new());
self.spawn(waiter(sink, self.tx(), notify.clone())); self.spawn(waiter(sink, self.tx(), notify.clone()));

View File

@ -26,8 +26,8 @@ pub enum Error {
#[error("C string null error")] #[error("C string null error")]
FfiNull(#[from] std::ffi::NulError), FfiNull(#[from] std::ffi::NulError),
#[error("audio playing error")] #[error("error interfacing with audio")]
Rodio(#[from] rodio::StreamError), Rodio(#[from] rodio::DeviceSinkError),
#[error("couldn't send internal message")] #[error("couldn't send internal message")]
Send(#[from] mpsc::error::SendError<crate::Message>), Send(#[from] mpsc::error::SendError<crate::Message>),

View File

@ -59,7 +59,7 @@ pub struct Player {
rx: Receiver<crate::Message>, rx: Receiver<crate::Message>,
/// Shared audio sink used for playback. /// Shared audio sink used for playback.
sink: Arc<rodio::Sink>, sink: Arc<rodio::Player>,
/// UI handle for rendering and input. /// UI handle for rendering and input.
ui: ui::Handle, ui: ui::Handle,
@ -105,7 +105,7 @@ impl Player {
tx.send(Message::Init).await?; tx.send(Message::Init).await?;
let list = List::load(args.track_list.as_ref()).await?; let list = List::load(args.track_list.as_ref()).await?;
let sink = Arc::new(rodio::Sink::connect_new(mixer)); let sink = Arc::new(rodio::Player::connect_new(mixer));
let state = ui::State::initial(Arc::clone(&sink), list.name.clone()); let state = ui::State::initial(Arc::clone(&sink), list.name.clone());
let volume = PersistentVolume::load().await?; let volume = PersistentVolume::load().await?;

View File

@ -133,7 +133,7 @@ mod interface {
#[tokio::test] #[tokio::test]
async fn loading() { async fn loading() {
let sink = Arc::new(rodio::Sink::new().0); let sink = Arc::new(rodio::Player::new().0);
let mut state = State::initial(sink, String::from("test")); let mut state = State::initial(sink, String::from("test"));
let menu = Interface::default().menu(&mut state); let menu = Interface::default().menu(&mut state);
@ -152,7 +152,7 @@ mod interface {
#[tokio::test] #[tokio::test]
async fn volume() { async fn volume() {
let sink = Arc::new(rodio::Sink::new().0); let sink = Arc::new(rodio::Player::new().0);
sink.set_volume(0.5); sink.set_volume(0.5);
let mut state = State::initial(sink, String::from("test")); let mut state = State::initial(sink, String::from("test"));
@ -174,7 +174,7 @@ mod interface {
#[tokio::test] #[tokio::test]
async fn progress() { async fn progress() {
let sink = Arc::new(rodio::Sink::new().0); let sink = Arc::new(rodio::Player::new().0);
Progress::new().set(0.5); Progress::new().set(0.5);
let mut state = State::initial(sink, String::from("test")); let mut state = State::initial(sink, String::from("test"));
state.current = Current::Loading(Some(Progress::new())); state.current = Current::Loading(Some(Progress::new()));
@ -196,7 +196,7 @@ mod interface {
#[tokio::test] #[tokio::test]
async fn track() { async fn track() {
let sink = Arc::new(rodio::Sink::new().0); let sink = Arc::new(rodio::Player::new().0);
let track = tracks::Info { let track = tracks::Info {
path: "/path".to_owned(), path: "/path".to_owned(),
display: "Test Track".to_owned(), display: "Test Track".to_owned(),

View File

@ -54,7 +54,7 @@ pub enum Error {
#[derive(Clone)] #[derive(Clone)]
pub struct State { pub struct State {
/// The audio sink. /// The audio sink.
pub sink: Arc<rodio::Sink>, pub sink: Arc<rodio::Player>,
/// The current track, which is updated by way of an [`Update`]. /// The current track, which is updated by way of an [`Update`].
pub current: Current, pub current: Current,
@ -72,7 +72,7 @@ pub struct State {
impl State { impl State {
/// Creates an initial UI state. /// Creates an initial UI state.
pub fn initial(sink: Arc<rodio::Sink>, list: String) -> Self { pub fn initial(sink: Arc<rodio::Player>, list: String) -> Self {
Self { Self {
sink, sink,
tracklist: list, tracklist: list,

View File

@ -12,7 +12,6 @@ use mpris_server::{
LoopStatus, Metadata, PlaybackRate, PlaybackStatus, PlayerInterface, Property, RootInterface, LoopStatus, Metadata, PlaybackRate, PlaybackStatus, PlayerInterface, Property, RootInterface,
Time, TrackId, Volume, Time, TrackId, Volume,
}; };
use rodio::Sink;
use tokio::sync::{broadcast, mpsc}; use tokio::sync::{broadcast, mpsc};
use crate::{player::Current, ui::Update}; use crate::{player::Current, ui::Update};
@ -52,7 +51,7 @@ impl Into<fdo::Error> for crate::Error {
/// The actual MPRIS player. /// The actual MPRIS player.
pub struct Player { pub struct Player {
sink: Arc<Sink>, sink: Arc<rodio::Player>,
current: ArcSwap<Current>, current: ArcSwap<Current>,
list: String, list: String,
sender: Sender, sender: Sender,