Krolyxon
Commit 05c4b17

rmptui05c4b17

damn

Author
krolxon
Date
2024-04-23 19:16 +0530
Parent
a0582ea
Commit
05c4b17bc078df9c5694e450b72aecbed9fc5216

+146 −33

6 files changed

  1. M src/app.rs +27 −11
  2. M src/connection.rs +39 −4
  3. M src/handler.rs +38 −6
  4. M src/list.rs +4 −2
  5. M src/main.rs +1 −1
  6. M src/ui.rs +37 −9
M src/app.rs View
@@ -1,5 +1,6 @@
1−use crate::connection::Connection;
1+use crate::connection::{self, Connection};
22 use crate::list::ContentList;
3+use mpd::Client;
34 use std::collections::VecDeque;
45
56 // Application result type
@@ -12,20 +13,30 @@ pub struct App {
1213 pub running: bool,
1314 pub conn: Connection,
1415 pub play_deque: VecDeque<String>,
15− pub list: ContentList,
16+ pub song_list: ContentList<String>,
17+ pub queue_list: ContentList<String>,
18+ pub pl_list: ContentList<String>,
1619 }
1720
1821 impl App {
19− pub fn new(addrs: &str) -> Self {
22+ pub fn builder(addrs: &str) -> AppResult<Self> {
2023 let mut conn = Connection::new(addrs).unwrap();
2124 let mut vec: VecDeque<String> = VecDeque::new();
25+ let mut pl_list = ContentList::new();
26+ pl_list.list = Self::get_playlist(&mut conn.conn)?;
2227 Self::get_queue(&mut conn, &mut vec);
23− Self {
28+
29+ let mut song_list = ContentList::new();
30+ song_list.list = conn.songs_filenames.clone();
31+
32+ Ok(Self {
2433 running: true,
2534 conn,
2635 play_deque: vec,
27− list: ContentList::new(),
28− }
36+ song_list,
37+ queue_list: ContentList::new(),
38+ pl_list,
39+ })
2940 }
3041
3142 pub fn tick(&self) {}
@@ -52,10 +63,15 @@ impl App {
5263 self.play_deque.clear();
5364 Self::get_queue(&mut self.conn, &mut self.play_deque);
5465 }
55−}
5666
57−fn to_vecdeque(filenames: &Vec<String>) -> VecDeque<String> {
58− let mut v: VecDeque<String> = VecDeque::new();
59− v = filenames.iter().map(|x| x.to_string()).collect();
60− v
67+ pub fn get_playlist(conn: &mut Client) -> AppResult<Vec<String>> {
68+ let list: Vec<String> = conn.playlists()?.iter().map(|p| p.clone().name).collect();
69+
70+ Ok(list)
71+ }
72+
73+ pub fn update_playlist(&mut self) -> AppResult<()> {
74+ Self::get_playlist(&mut self.conn.conn)?;
75+ Ok(())
76+ }
6177 }
M src/connection.rs View
@@ -10,6 +10,7 @@ pub type Error = Box<dyn std::error::Error>;
1010 pub struct Connection {
1111 pub conn: Client,
1212 pub songs_filenames: Vec<String>,
13+ // pub state: String,
1314 }
1415
1516 impl Connection {
@@ -25,6 +26,7 @@ impl Connection {
2526 Ok(Self {
2627 conn,
2728 songs_filenames,
29+ // state: "Stopped".to_string(),
2830 })
2931 }
3032
@@ -50,14 +52,22 @@ impl Connection {
5052 Ok(())
5153 }
5254
55+ // pub fn update_state(&mut self) {
56+ // match self.conn.status().unwrap().state {
57+ // State::Stop => self.state = "Stopped".to_string(),
58+ // State::Play => self.state = "Playing".to_string(),
59+ // State::Pause => self.state = "Paused".to_string(),
60+ // }
61+ // }
62+
5363 pub fn push(&mut self, song: &Song) -> Result<()> {
5464 if self.conn.queue().unwrap().is_empty() {
5565 self.conn.push(song).unwrap();
5666 self.conn.play().unwrap();
5767 } else {
58− self.conn.push(song).unwrap();
59− if self.conn.status().unwrap().state == State::Stop {
60− self.conn.play().unwrap();
68+ self.conn.push(song)?;
69+ if self.conn.status()?.state == State::Stop {
70+ self.conn.play()?;
6171 }
6272 self.conn.next().unwrap();
6373 }
@@ -65,6 +75,19 @@ impl Connection {
6575 Ok(())
6676 }
6777
78+ pub fn push_playlist(&mut self, playlist: &str) -> Result<()> {
79+ let songs: Vec<Song> = self.conn.playlist(playlist)?;
80+
81+ for song in songs {
82+ if self.songs_filenames.contains(&song.file) {
83+ let song = self.get_song_with_only_filename(&song.file);
84+ self.conn.push(&song)?;
85+ self.conn.play()?;
86+ }
87+ }
88+ Ok(())
89+ }
90+
6891 pub fn get_song_with_only_filename(&self, filename: &str) -> Song {
6992 Song {
7093 file: filename.to_string(),
@@ -81,7 +104,6 @@ impl Connection {
81104
82105 pub fn get_current_song(&mut self) -> Option<String> {
83106 self.conn.currentsong().unwrap().unwrap_or_default().title
84−
85107 }
86108 pub fn status(&mut self) {
87109 let current_song = self.conn.currentsong();
@@ -99,6 +121,19 @@ impl Connection {
99121 );
100122 }
101123
124+ pub fn now_playing(&mut self) -> Option<String> {
125+ let song = self.conn.currentsong().unwrap().unwrap_or_default();
126+ if let Some(s) = song.title {
127+ if let Some(a) = song.artist {
128+ Some(format!("{} - {}", s, a))
129+ } else {
130+ Some(s)
131+ }
132+ } else {
133+ None
134+ }
135+ }
136+
102137 // Playback controls
103138 pub fn pause(&mut self) {
104139 self.conn.pause(true).unwrap();
M src/handler.rs View
@@ -11,17 +11,17 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
1111 }
1212
1313 KeyCode::Char('j') => {
14− app.list.next();
14+ app.song_list.next();
1515 }
1616
1717 KeyCode::Char('k') => {
18− app.list.prev();
18+ app.song_list.prev();
1919 }
2020
2121 KeyCode::Enter | KeyCode::Char('l') => {
22− let song = app.conn.get_song_with_only_filename(app.conn.songs_filenames.get(app.list.index).unwrap());
23− app.conn.push(&song).unwrap();
24− app.update_queue();
22+ let song = app.conn.get_song_with_only_filename(app.conn.songs_filenames.get(app.song_list.index).unwrap());
23+ app.conn.push(&song)?;
24+ // app.update_queue();
2525 }
2626
2727 // Playback controls
@@ -35,10 +35,42 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
3535 app.conn.pause();
3636 }
3737
38+
3839 // Clearn Queue
3940 KeyCode::Char('x') => {
4041 app.conn.conn.clear()?;
41− app.update_queue();
42+ // app.update_queue();
43+ }
44+
45+ KeyCode::Char('d') => {
46+ app.conn.play_dmenu()?;
47+ }
48+
49+ KeyCode::Down=> {
50+ app.pl_list.next();
51+ }
52+
53+ KeyCode::Up=> {
54+ app.pl_list.prev();
55+ }
56+
57+
58+ KeyCode::Right => {
59+ app.conn.push_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
60+ }
61+
62+ KeyCode::Char('f')=> {
63+ // let place = app.conn.conn.status().unwrap().duration;
64+ let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
65+ let pos: i64 = (pos.as_secs() + 2).try_into().unwrap();
66+ app.conn.conn.seek(2, pos )?;
67+ }
68+
69+ KeyCode::Char('b')=> {
70+ // let place = app.conn.conn.status().unwrap().duration;
71+ let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
72+ let pos: i64 = (pos.as_secs() - 2).try_into().unwrap();
73+ app.conn.conn.seek(2, pos )?;
4274 }
4375 _ => {}
4476 }
M src/list.rs View
@@ -1,11 +1,13 @@
11 #[derive(Debug)]
2−pub struct ContentList {
2+pub struct ContentList<T> {
3+ pub list: Vec<T>,
34 pub index: usize
45 }
56
6−impl ContentList {
7+impl<T> ContentList<T> {
78 pub fn new() -> Self {
89 ContentList {
10+ list: Vec::new(),
911 index: 0
1012 }
1113 }
M src/main.rs View
@@ -42,7 +42,7 @@ fn main() -> AppResult<()> {
4242
4343 let backend = CrosstermBackend::new(io::stderr());
4444 let terminal = Terminal::new(backend)?;
45− let mut app = App::new("127.0.0.1:6600");
45+ let mut app = App::builder("127.0.0.1:6600")?;
4646 let events = EventHandler::new(250);
4747
4848 let mut tui = tui::Tui::new(terminal, events);
M src/ui.rs View
@@ -1,4 +1,4 @@
1−use crate::{app::App, connection::Connection};
1+use crate::app::App;
22 use ratatui::{prelude::*, widgets::*};
33
44 /// Renders the user interface widgets
@@ -9,7 +9,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
99 // - https://github.com/ratatui-org/ratatui/tree/master/examples
1010
1111 // List of songs
12− let mut state = ListState::default();
12+ let mut song_state = ListState::default();
1313 let size = Rect::new(100, 0, frame.size().width, frame.size().height - 3);
1414 let list = List::new(app.conn.songs_filenames.clone())
1515 .block(Block::default().title("Song List").borders(Borders::ALL))
@@ -17,21 +17,49 @@ pub fn render(app: &mut App, frame: &mut Frame) {
1717 .highlight_symbol(">>")
1818 .repeat_highlight_symbol(true);
1919
20− state.select(Some(app.list.index));
21− frame.render_stateful_widget(list, size, &mut state);
20+ song_state.select(Some(app.song_list.index));
21+ frame.render_stateful_widget(list, size, &mut song_state);
2222
2323 // Play Queue
24+ let mut queue_state = ListState::default();
2425 let size = Rect::new(0, 0, 100, frame.size().height - 25);
2526 let list = List::new(app.play_deque.clone())
2627 .block(Block::default().title("Play Queue").borders(Borders::ALL))
2728 .highlight_style(Style::new().add_modifier(Modifier::REVERSED))
2829 .highlight_symbol(">>")
2930 .repeat_highlight_symbol(true);
30− frame.render_widget(list, size);
31+
32+ app.update_queue();
33+ frame.render_stateful_widget(list, size, &mut queue_state);
3134
3235 // Status
33− let size = Rect::new(0, frame.size().height - 3, frame.size().width, 3);
34− let status = Paragraph::new(app.conn.conn.status().unwrap().volume.to_string())
35− .block(Block::default().title("Status").borders(Borders::ALL));
36− frame.render_widget(status, size);
36+ // let size = Rect::new(0, frame.size().height - 3, frame.size().width, 3);
37+ // let song = app
38+ // .conn
39+ // .now_playing()
40+ // .unwrap_or_else(|| "No Title Found".to_string());
41+ //
42+ // let (elapsed, total) = app.conn.conn.status().unwrap().time.unwrap();
43+ //
44+ // let mut lines = vec![];
45+ // lines.push(Line::from(vec![
46+ // Span::styled("Current: ", Style::default().fg(Color::Red)),
47+ // Span::styled(song, Style::default().fg(Color::Yellow)),
48+ // Span::styled(format!("[{}/{}]", elapsed.as_secs(), total.as_secs()), Style::default().fg(Color::Yellow)),
49+ // ]));
50+ // let status = Paragraph::new(Text::from(lines))
51+ // .block(Block::default().title("Status").borders(Borders::ALL));
52+ // frame.render_widget(status, size);
53+
54+ // Playlists
55+ let mut state = ListState::default();
56+ let size = Rect::new(0, 25, 100, frame.size().height - 25 - 3);
57+ let list = List::new(app.pl_list.list.clone())
58+ .block(Block::default().title("Playlists").borders(Borders::ALL))
59+ .highlight_style(Style::new().add_modifier(Modifier::REVERSED))
60+ .highlight_symbol(">>")
61+ .repeat_highlight_symbol(true);
62+
63+ state.select(Some(app.pl_list.index));
64+ frame.render_stateful_widget(list, size, &mut state);
3765 }