diff --git a/src/action.rs b/src/action.rs index c3f5ec3..4ac2e57 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; +/// Action that can be performed in the application #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Action { Tick, diff --git a/src/app.rs b/src/app.rs index 2415a48..2ff71bc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,5 @@ use color_eyre::eyre::Result; use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent}; -use rand::seq::index; use ratatui::{ Terminal, buffer::Buffer, @@ -12,12 +11,12 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use std::io::Stdout; use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; -use tracing::{debug, info}; +use tracing::{debug, error, info}; use crate::{ action::Action, event::{Event, Events}, - player::{self, Player}, + player::Player, subsonic_helper, widgets::Queue, }; @@ -85,6 +84,7 @@ impl App { } while let Ok(action) = self.rx.try_recv() { if let Err(e) = self.handle_action(action.clone()) { + error!("Error handling action: {e}"); self.popup = Some(("Error".to_string(), format!("{e}"))) }; if matches!(action, Action::Resize(_, _) | Action::Render) { diff --git a/src/main.rs b/src/main.rs index e0e2ef3..28c45a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod widgets; use color_eyre::eyre::Result; use dotenv::dotenv; +use tracing::info; #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { @@ -18,11 +19,13 @@ async fn main() -> Result<()> { logging::init()?; set_panic_hook(); + info!("Starting TUI..."); let terminal = ratatui::init(); let events = event::Events::new(); app::App::new().run(terminal, events).await?; ratatui::restore(); + info!("Exited TUI. Bye"); Ok(()) } diff --git a/src/player.rs b/src/player.rs index a2e50f7..dc600ff 100644 --- a/src/player.rs +++ b/src/player.rs @@ -3,6 +3,7 @@ use cpal::traits::HostTrait; use futures::StreamExt; use reqwest::Client; use rodio::{OutputStream, Sink, Source}; +use tracing::debug; use std::fs::{self, File}; use std::io::BufReader; use std::sync::{Arc, Mutex}; @@ -23,6 +24,7 @@ pub struct Player { _stream: OutputStream, } +/// Responsible to store the queue, current playing song and play songs as requested impl Player { pub fn new(tx: UnboundedSender) -> Result { let device = cpal::host_from_id(cpal::available_hosts() @@ -44,12 +46,16 @@ impl Player { }) } + /// Will try to play the song in the queue at the specified index + /// Download file if it does not exist yet + /// In any case try to create a decoder from it and send action to add it to the sink pub fn try_play(&self, index: usize, client: Client) -> Result<()> { let id = self.songs_list.lock().unwrap()[index].id.clone(); let mut path = config::temp_dir(); path.push(format!("{id}.mp3")); if !path.exists() { + debug!("{id} does not exist. Starting download"); let client = client.clone(); let id = id.clone(); tokio::spawn(async move { async_audio_dl(id, client).await }); @@ -76,17 +82,26 @@ impl Player { Ok(()) } + /// Add the song specified by the index to the sink pub fn add_to_sink(&mut self, index: usize) -> Result<()> { + // Retrieve file from index let id = self.songs_list.lock().unwrap()[index].id.clone(); let mut path = config::temp_dir(); path.push(format!("{id}.mp3")); let file = std::fs::File::open(&path)?; + let decoder = rodio::Decoder::new(BufReader::new(file))?; + // This help having a constant volume let agc_source = decoder.automatic_gain_control(1.0, 4.0, 0.005, 5.0); + if self.sink.empty() { + // set only if is first to be added to sink self.current_playing = index; } + self.sink.append(agc_source); + debug!("{id} added to sink"); + let tx = self.tx.clone(); self.sink .append(rodio::source::EmptyCallback::new(Box::new(move || { diff --git a/src/widgets/queue.rs b/src/widgets/queue.rs index ee0f290..6511cf7 100644 --- a/src/widgets/queue.rs +++ b/src/widgets/queue.rs @@ -5,7 +5,6 @@ use ratatui::{ widgets::{StatefulWidget, Table, TableState}, }; use std::sync::{Arc, Mutex}; -use std::usize; use style::Styled; use subsonic_types::response::Child; @@ -16,6 +15,7 @@ pub struct Queue { current_playing: usize, } +/// Render the song_list highlighting the row at current_playing index impl Queue { pub fn new(songs_list: Arc>>, current_playing: usize) -> Self { Self {