Krolyxon
Commit bc0348e

rmptuisrcconnection.rs

130 lines · 4.0 KB · Rust

1use mpd::song::Song;
2use mpd::{Client, State};
3use simple_dmenu::dmenu;
4
5pub struct Connection {
6 pub conn: Client,
7 pub songs_filenames: Vec<String>,
8}
9
10impl Connection {
11 pub fn new(addrs: &str) -> Result<Self, mpd::error::Error> {
12 let mut conn = Client::connect(addrs)?;
13 let mut songs_filenames: Vec<String> = Vec::new();
14 get_file_tree_into_vec(&mut conn, &mut songs_filenames, ".", ".");
15
16 Ok(Self {
17 conn,
18 songs_filenames,
19 })
20 }
21
22 pub fn play_fzf(&mut self) {
23 let ss = &self.songs_filenames;
24 let fzf_choice = rust_fzf::select(ss.clone(), Vec::new()).unwrap();
25 let index = get_choice_index(&self.songs_filenames, fzf_choice.get(0).unwrap());
26 let song = self.get_song_with_only_filename(ss.get(index).unwrap());
27 self.push(&song);
28 }
29
30 pub fn play_dmenu(&mut self) {
31 let ss: Vec<&str> = self.songs_filenames.iter().map(|x| x.as_str()).collect();
32 let op = dmenu!(iter &ss; args "-l", "30");
33 let index = get_choice_index(&self.songs_filenames, &op);
34 let song = self.get_song_with_only_filename(ss.get(index).unwrap());
35 self.push(&song);
36 }
37
38 fn push(&mut self, song: &Song) {
39 if self.conn.queue().unwrap().is_empty() {
40 self.conn.push(song).unwrap();
41 self.conn.play().unwrap();
42 } else {
43 self.conn.push(song).unwrap();
44 if self.conn.status().unwrap().state == State::Stop {
45 self.conn.play().unwrap();
46 }
47 self.conn.next().unwrap();
48 }
49 }
50
51 fn get_song_with_only_filename(&self, filename: &str) -> Song {
52 Song {
53 file: filename.to_string(),
54 artist: None,
55 title: None,
56 duration: None,
57 last_mod: None,
58 name: None,
59 place: None,
60 range: None,
61 tags: vec![("".to_string(), "".to_string())],
62 }
63 }
64
65 pub fn status(&mut self) {
66 let current_song = self.conn.currentsong();
67 let status = self.conn.status().unwrap();
68
69 if current_song.is_ok() {
70 let song = current_song.unwrap();
71 if let Some(s) = song {
72 println!("{} - {}", s.artist.unwrap(), s.title.unwrap());
73 }
74 }
75 println!(
76 "volume: {}\trepeat: {}\trandom: {}\tsingle: {}\tconsume: {}",
77 status.volume, status.repeat, status.random, status.single, status.consume
78 );
79 }
80
81 // Play controls
82 pub fn pause(&mut self) {
83 self.conn.pause(true).unwrap();
84 }
85
86 pub fn toggle_pause(&mut self) {
87 self.conn.toggle_pause().unwrap();
88 }
89
90 // Volume controls
91 pub fn inc_volume(&mut self, inc: i8) {
92 let cur = self.conn.status().unwrap().volume;
93 self.conn.volume(cur + inc).unwrap();
94 }
95
96 pub fn dec_volume(&mut self, dec: i8) {
97 let cur = self.conn.status().unwrap().volume;
98 self.conn.volume(cur - dec).unwrap();
99 }
100}
101
102fn get_file_tree_into_vec(conn: &mut Client, vec: &mut Vec<String>, path: &str, dir_append: &str) {
103 let songs = conn.listfiles(path).unwrap_or_default();
104 for (i, s) in songs {
105 // Output of listfiles contains the last-modified thing, we dont want that
106 if i != "Last-Modified" {
107 if i == "directory" {
108 get_file_tree_into_vec(conn, vec, &s, &s);
109 } else {
110 // We parse the string as float because the output of listfiles contains some random numbers, we dont want that
111 if !s.parse::<f32>().is_ok() {
112 let mut sam: String = String::new();
113 sam.push_str(dir_append);
114 sam.push_str(r"/");
115 sam.push_str(s.as_str());
116 vec.push(sam);
117 }
118 }
119 }
120 }
121}
122
123fn get_choice_index(ss: &Vec<String>, selection: &str) -> usize {
124 let mut choice: usize = 0;
125 if let Some(index) = ss.iter().position(|s| s == selection) {
126 choice = index;
127 }
128
129 choice
130}