diff --git a/src/app.rs b/src/app.rs index 9e4183c..c411bb7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5,14 +5,15 @@ use std::io::BufReader; use crate::event::{AppEvent, Event, EventHandler}; use crate::library::{Library, Song}; -use audiotags::{MimeType, Tag}; -use crossterm::event::MediaKeyCode::{self, PlayPause}; +use crossterm::event::MediaKeyCode::{self}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use discord_rich_presence::activity::{Assets, Timestamps}; use discord_rich_presence::{DiscordIpc, DiscordIpcClient, activity}; use ratatui::DefaultTerminal; -use ratatui::widgets::{List, ListItem, ListState}; -use rodio::Decoder; +use ratatui::widgets::ListState; +use rodio::{ + Decoder, DeviceSinkBuilder, DeviceSinkError, MixerDeviceSink, Player, SampleRate, Source, +}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[derive(Debug, Default, PartialEq, Eq)] @@ -34,8 +35,10 @@ pub struct App { pub queue: VecDeque, - pub sink_handle: rodio::MixerDeviceSink, - pub player: rodio::Player, + pub sink_handle: MixerDeviceSink, + pub sample_rate: SampleRate, + pub sink_volume: f32, + pub player: Player, pub artist_state: ListState, pub album_state: ListState, @@ -57,9 +60,9 @@ impl App { /// Constructs a new instance of [`App`]. pub fn new() -> Self { let sink_handle = - rodio::DeviceSinkBuilder::open_default_sink().expect("open default audio stream"); - let player = rodio::Player::connect_new(sink_handle.mixer()); - player.set_volume(1.0); + DeviceSinkBuilder::open_default_sink().expect("open default audio stream"); + let player = Player::connect_new(sink_handle.mixer()); + // player.set_volume(1.0); let discord_client = { let mut client = DiscordIpcClient::new("1525954755292299426"); @@ -76,7 +79,6 @@ impl App { Self { running: true, library: Library::new(), - //songs: get_songs(), queue: vec![].into(), artist_state: ListState::default().with_selected(Some(0)), album_state: ListState::default().with_selected(Some(0)), @@ -89,6 +91,8 @@ impl App { paused_at: 1, sink_handle, player, + sink_volume: 1.0, + sample_rate: SampleRate::new(44100).unwrap(), discord_client, } } @@ -137,7 +141,7 @@ impl App { if self.control_popup == false { self.events.send(AppEvent::Quit) } else { - self.control_popup = !self.control_popup; + self.control_popup = !self.control_popup; } } KeyCode::Char('c' | 'C') if key_event.modifiers == KeyModifiers::CONTROL => { @@ -252,7 +256,8 @@ impl App { if vol >= 1.0 { self.player.set_volume(1.0); } else { - self.player.set_volume(vol + 0.05); + self.sink_volume = vol + 0.05; + self.player.set_volume(self.sink_volume); } } @@ -261,7 +266,8 @@ impl App { if vol <= 0.01 { self.player.set_volume(0.0); } else { - self.player.set_volume(vol - 0.05); + self.sink_volume = vol - 0.05; + self.player.set_volume(self.sink_volume); } } @@ -425,6 +431,13 @@ impl App { File::open(&self.library.songs[*self.queue.front().expect("Queue is empty")].path) .unwrap(); let source = Decoder::new(BufReader::new(file)).unwrap(); + + let rate: SampleRate = source.sample_rate(); + if rate != self.sample_rate { + self.sample_rate = rate; + let _ = self.rebuild_sink(self.sample_rate); + } + self.player.append(source); self.current_song = Some(self.queue.front().unwrap().to_owned()); self.update_rpc(self.queue.front().unwrap().to_owned()); @@ -444,6 +457,22 @@ impl App { } } + pub fn rebuild_sink(&mut self, rate: SampleRate) -> Result<(), DeviceSinkError> { + self.sink_handle.log_on_drop(false); + let mut sink = DeviceSinkBuilder::from_default_device() + .unwrap() + .with_sample_rate(rate) + .open_stream() + .unwrap(); + + sink.log_on_drop(false); + self.sink_handle = sink; + self.player = Player::connect_new(self.sink_handle.mixer()); + self.player.set_volume(self.sink_volume); + + Ok(()) + } + /// Set running to false to quit the application. pub fn quit(&mut self) { self.running = false; diff --git a/src/ui.rs b/src/ui.rs index 8ab2289..1272dba 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -50,8 +50,9 @@ impl Widget for &mut App { let now_playing_block = Block::bordered() .title(format!( - "Now Playing | Vol: {:.0}", - self.player.volume() * 100.0 + "Now Playing | Vol: {:.0} | Rate: {}Hz", + self.player.volume() * 100.0, + self.sample_rate )) .border_type(Rounded); let inner = now_playing_block.inner(center_area[1]);