damn
This commit is contained in:
parent
a0582ead78
commit
05c4b17bc0
38
src/app.rs
38
src/app.rs
|
|
@ -1,5 +1,6 @@
|
|||
use crate::connection::Connection;
|
||||
use crate::connection::{self, Connection};
|
||||
use crate::list::ContentList;
|
||||
use mpd::Client;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
// Application result type
|
||||
|
|
@ -12,20 +13,30 @@ pub struct App {
|
|||
pub running: bool,
|
||||
pub conn: Connection,
|
||||
pub play_deque: VecDeque<String>,
|
||||
pub list: ContentList,
|
||||
pub song_list: ContentList<String>,
|
||||
pub queue_list: ContentList<String>,
|
||||
pub pl_list: ContentList<String>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(addrs: &str) -> Self {
|
||||
pub fn builder(addrs: &str) -> AppResult<Self> {
|
||||
let mut conn = Connection::new(addrs).unwrap();
|
||||
let mut vec: VecDeque<String> = VecDeque::new();
|
||||
let mut pl_list = ContentList::new();
|
||||
pl_list.list = Self::get_playlist(&mut conn.conn)?;
|
||||
Self::get_queue(&mut conn, &mut vec);
|
||||
Self {
|
||||
|
||||
let mut song_list = ContentList::new();
|
||||
song_list.list = conn.songs_filenames.clone();
|
||||
|
||||
Ok(Self {
|
||||
running: true,
|
||||
conn,
|
||||
play_deque: vec,
|
||||
list: ContentList::new(),
|
||||
}
|
||||
song_list,
|
||||
queue_list: ContentList::new(),
|
||||
pl_list,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn tick(&self) {}
|
||||
|
|
@ -52,10 +63,15 @@ impl App {
|
|||
self.play_deque.clear();
|
||||
Self::get_queue(&mut self.conn, &mut self.play_deque);
|
||||
}
|
||||
}
|
||||
|
||||
fn to_vecdeque(filenames: &Vec<String>) -> VecDeque<String> {
|
||||
let mut v: VecDeque<String> = VecDeque::new();
|
||||
v = filenames.iter().map(|x| x.to_string()).collect();
|
||||
v
|
||||
pub fn get_playlist(conn: &mut Client) -> AppResult<Vec<String>> {
|
||||
let list: Vec<String> = conn.playlists()?.iter().map(|p| p.clone().name).collect();
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
|
||||
pub fn update_playlist(&mut self) -> AppResult<()> {
|
||||
Self::get_playlist(&mut self.conn.conn)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub type Error = Box<dyn std::error::Error>;
|
|||
pub struct Connection {
|
||||
pub conn: Client,
|
||||
pub songs_filenames: Vec<String>,
|
||||
// pub state: String,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
|
|
@ -25,6 +26,7 @@ impl Connection {
|
|||
Ok(Self {
|
||||
conn,
|
||||
songs_filenames,
|
||||
// state: "Stopped".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -50,14 +52,22 @@ impl Connection {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn update_state(&mut self) {
|
||||
// match self.conn.status().unwrap().state {
|
||||
// State::Stop => self.state = "Stopped".to_string(),
|
||||
// State::Play => self.state = "Playing".to_string(),
|
||||
// State::Pause => self.state = "Paused".to_string(),
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn push(&mut self, song: &Song) -> Result<()> {
|
||||
if self.conn.queue().unwrap().is_empty() {
|
||||
self.conn.push(song).unwrap();
|
||||
self.conn.play().unwrap();
|
||||
} else {
|
||||
self.conn.push(song).unwrap();
|
||||
if self.conn.status().unwrap().state == State::Stop {
|
||||
self.conn.play().unwrap();
|
||||
self.conn.push(song)?;
|
||||
if self.conn.status()?.state == State::Stop {
|
||||
self.conn.play()?;
|
||||
}
|
||||
self.conn.next().unwrap();
|
||||
}
|
||||
|
|
@ -65,6 +75,19 @@ impl Connection {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_playlist(&mut self, playlist: &str) -> Result<()> {
|
||||
let songs: Vec<Song> = self.conn.playlist(playlist)?;
|
||||
|
||||
for song in songs {
|
||||
if self.songs_filenames.contains(&song.file) {
|
||||
let song = self.get_song_with_only_filename(&song.file);
|
||||
self.conn.push(&song)?;
|
||||
self.conn.play()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_song_with_only_filename(&self, filename: &str) -> Song {
|
||||
Song {
|
||||
file: filename.to_string(),
|
||||
|
|
@ -81,7 +104,6 @@ impl Connection {
|
|||
|
||||
pub fn get_current_song(&mut self) -> Option<String> {
|
||||
self.conn.currentsong().unwrap().unwrap_or_default().title
|
||||
|
||||
}
|
||||
pub fn status(&mut self) {
|
||||
let current_song = self.conn.currentsong();
|
||||
|
|
@ -99,6 +121,19 @@ impl Connection {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn now_playing(&mut self) -> Option<String> {
|
||||
let song = self.conn.currentsong().unwrap().unwrap_or_default();
|
||||
if let Some(s) = song.title {
|
||||
if let Some(a) = song.artist {
|
||||
Some(format!("{} - {}", s, a))
|
||||
} else {
|
||||
Some(s)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
pub fn pause(&mut self) {
|
||||
self.conn.pause(true).unwrap();
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
|
|||
}
|
||||
|
||||
KeyCode::Char('j') => {
|
||||
app.list.next();
|
||||
app.song_list.next();
|
||||
}
|
||||
|
||||
KeyCode::Char('k') => {
|
||||
app.list.prev();
|
||||
app.song_list.prev();
|
||||
}
|
||||
|
||||
KeyCode::Enter | KeyCode::Char('l') => {
|
||||
let song = app.conn.get_song_with_only_filename(app.conn.songs_filenames.get(app.list.index).unwrap());
|
||||
app.conn.push(&song).unwrap();
|
||||
app.update_queue();
|
||||
let song = app.conn.get_song_with_only_filename(app.conn.songs_filenames.get(app.song_list.index).unwrap());
|
||||
app.conn.push(&song)?;
|
||||
// app.update_queue();
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
|
|
@ -35,10 +35,42 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
|
|||
app.conn.pause();
|
||||
}
|
||||
|
||||
|
||||
// Clearn Queue
|
||||
KeyCode::Char('x') => {
|
||||
app.conn.conn.clear()?;
|
||||
app.update_queue();
|
||||
// app.update_queue();
|
||||
}
|
||||
|
||||
KeyCode::Char('d') => {
|
||||
app.conn.play_dmenu()?;
|
||||
}
|
||||
|
||||
KeyCode::Down=> {
|
||||
app.pl_list.next();
|
||||
}
|
||||
|
||||
KeyCode::Up=> {
|
||||
app.pl_list.prev();
|
||||
}
|
||||
|
||||
|
||||
KeyCode::Right => {
|
||||
app.conn.push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
|
||||
}
|
||||
|
||||
KeyCode::Char('f')=> {
|
||||
// let place = app.conn.conn.status().unwrap().duration;
|
||||
let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
|
||||
let pos: i64 = (pos.as_secs() + 2).try_into().unwrap();
|
||||
app.conn.conn.seek(2, pos )?;
|
||||
}
|
||||
|
||||
KeyCode::Char('b')=> {
|
||||
// let place = app.conn.conn.status().unwrap().duration;
|
||||
let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
|
||||
let pos: i64 = (pos.as_secs() - 2).try_into().unwrap();
|
||||
app.conn.conn.seek(2, pos )?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
#[derive(Debug)]
|
||||
pub struct ContentList {
|
||||
pub struct ContentList<T> {
|
||||
pub list: Vec<T>,
|
||||
pub index: usize
|
||||
}
|
||||
|
||||
impl ContentList {
|
||||
impl<T> ContentList<T> {
|
||||
pub fn new() -> Self {
|
||||
ContentList {
|
||||
list: Vec::new(),
|
||||
index: 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ fn main() -> AppResult<()> {
|
|||
|
||||
let backend = CrosstermBackend::new(io::stderr());
|
||||
let terminal = Terminal::new(backend)?;
|
||||
let mut app = App::new("127.0.0.1:6600");
|
||||
let mut app = App::builder("127.0.0.1:6600")?;
|
||||
let events = EventHandler::new(250);
|
||||
|
||||
let mut tui = tui::Tui::new(terminal, events);
|
||||
|
|
|
|||
46
src/ui.rs
46
src/ui.rs
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{app::App, connection::Connection};
|
||||
use crate::app::App;
|
||||
use ratatui::{prelude::*, widgets::*};
|
||||
|
||||
/// Renders the user interface widgets
|
||||
|
|
@ -9,7 +9,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
|
|||
// - https://github.com/ratatui-org/ratatui/tree/master/examples
|
||||
|
||||
// List of songs
|
||||
let mut state = ListState::default();
|
||||
let mut song_state = ListState::default();
|
||||
let size = Rect::new(100, 0, frame.size().width, frame.size().height - 3);
|
||||
let list = List::new(app.conn.songs_filenames.clone())
|
||||
.block(Block::default().title("Song List").borders(Borders::ALL))
|
||||
|
|
@ -17,21 +17,49 @@ pub fn render(app: &mut App, frame: &mut Frame) {
|
|||
.highlight_symbol(">>")
|
||||
.repeat_highlight_symbol(true);
|
||||
|
||||
state.select(Some(app.list.index));
|
||||
frame.render_stateful_widget(list, size, &mut state);
|
||||
song_state.select(Some(app.song_list.index));
|
||||
frame.render_stateful_widget(list, size, &mut song_state);
|
||||
|
||||
// Play Queue
|
||||
let mut queue_state = ListState::default();
|
||||
let size = Rect::new(0, 0, 100, frame.size().height - 25);
|
||||
let list = List::new(app.play_deque.clone())
|
||||
.block(Block::default().title("Play Queue").borders(Borders::ALL))
|
||||
.highlight_style(Style::new().add_modifier(Modifier::REVERSED))
|
||||
.highlight_symbol(">>")
|
||||
.repeat_highlight_symbol(true);
|
||||
frame.render_widget(list, size);
|
||||
|
||||
app.update_queue();
|
||||
frame.render_stateful_widget(list, size, &mut queue_state);
|
||||
|
||||
// Status
|
||||
let size = Rect::new(0, frame.size().height - 3, frame.size().width, 3);
|
||||
let status = Paragraph::new(app.conn.conn.status().unwrap().volume.to_string())
|
||||
.block(Block::default().title("Status").borders(Borders::ALL));
|
||||
frame.render_widget(status, size);
|
||||
// let size = Rect::new(0, frame.size().height - 3, frame.size().width, 3);
|
||||
// let song = app
|
||||
// .conn
|
||||
// .now_playing()
|
||||
// .unwrap_or_else(|| "No Title Found".to_string());
|
||||
//
|
||||
// let (elapsed, total) = app.conn.conn.status().unwrap().time.unwrap();
|
||||
//
|
||||
// let mut lines = vec![];
|
||||
// lines.push(Line::from(vec![
|
||||
// Span::styled("Current: ", Style::default().fg(Color::Red)),
|
||||
// Span::styled(song, Style::default().fg(Color::Yellow)),
|
||||
// Span::styled(format!("[{}/{}]", elapsed.as_secs(), total.as_secs()), Style::default().fg(Color::Yellow)),
|
||||
// ]));
|
||||
// let status = Paragraph::new(Text::from(lines))
|
||||
// .block(Block::default().title("Status").borders(Borders::ALL));
|
||||
// frame.render_widget(status, size);
|
||||
|
||||
// Playlists
|
||||
let mut state = ListState::default();
|
||||
let size = Rect::new(0, 25, 100, frame.size().height - 25 - 3);
|
||||
let list = List::new(app.pl_list.list.clone())
|
||||
.block(Block::default().title("Playlists").borders(Borders::ALL))
|
||||
.highlight_style(Style::new().add_modifier(Modifier::REVERSED))
|
||||
.highlight_symbol(">>")
|
||||
.repeat_highlight_symbol(true);
|
||||
|
||||
state.select(Some(app.pl_list.index));
|
||||
frame.render_stateful_widget(list, size, &mut state);
|
||||
}
|
||||
|
|
|
|||
Reference in New Issue