From 579b09b61dd15776244a060d99e7d704eb651c33 Mon Sep 17 00:00:00 2001 From: krolxon Date: Mon, 22 Apr 2024 13:02:31 +0530 Subject: [PATCH] add dmenu selector --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/connection.rs | 119 ++++++++++++++++++++++++++++++---------------- src/main.rs | 24 +++++++++- 4 files changed, 108 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 430356b..ba402c3 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,6 +142,7 @@ dependencies = [ "clap", "mpd", "rust_fzf", + "simple-dmenu", ] [[package]] @@ -150,6 +151,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a94b9c6a9880356cc6de038a52397509f8ac86a18c30d76da904b08fec2cb1" +[[package]] +name = "simple-dmenu" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f392360283341235b298e79f0360bd924db6e6ad1e0964cbf4c43ea79c237eb" + [[package]] name = "strsim" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 59d71b8..b1aeb39 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" mpd = "0.1.0" clap = { version = "4.0.29", features = ["derive"] } rust_fzf = "0.3.1" +simple-dmenu = "0.1.0" diff --git a/src/connection.rs b/src/connection.rs index ebc847f..71db995 100755 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,66 +1,53 @@ use mpd::song::Song; use mpd::Client; +use simple_dmenu::dmenu; +use std::process::Command; pub struct Connection { pub conn: Client, + pub songs_filenames: Vec, } impl Connection { pub fn new(addrs: &str) -> Result { - let conn = Client::connect(addrs)?; - Ok(Self { conn }) + let mut conn = Client::connect(addrs)?; + let mut songs_filenames: Vec = Vec::new(); + get_file_tree_into_vec(&mut conn, &mut songs_filenames, ".", "."); + + Ok(Self { + conn, + songs_filenames, + }) } pub fn play_fzf(&mut self) { - let mut ss: Vec = Vec::new(); - self.get_file_tree_into_vec(&mut ss, ".", "."); - - let choice: usize; + let ss = &self.songs_filenames; let fzf_choice = rust_fzf::select(ss.clone(), Vec::new()).unwrap(); - if let Some(index) = ss.iter().position(|s| s == fzf_choice.get(0).unwrap()) { - choice = index; - } else { - return; - } + let index = get_choice_index(&self.songs_filenames, fzf_choice.get(0).unwrap()); + let song = self.get_song_with_only_filename(ss.get(index).unwrap()); + self.push(&song); + } - let song = self.get_song(ss.get(choice).unwrap()); + pub fn play_dmenu(&mut self) { + let ss: Vec<&str> = self.songs_filenames.iter().map(|x| x.as_str()).collect(); + let op = dmenu!(iter &ss; args "-l", "30"); + let index = get_choice_index(&self.songs_filenames, &op); + let song = self.get_song_with_only_filename(ss.get(index).unwrap()); + self.push(&song); + } + fn push(&mut self, song: &Song) { + self.conn.push(song).unwrap(); if self.conn.queue().unwrap().is_empty() { - self.push(song); + self.conn.push(song).unwrap(); self.conn.play().unwrap(); } else { - self.push(song); + self.conn.push(song).unwrap(); self.conn.next().unwrap(); } } - fn get_file_tree_into_vec(&mut self, vec: &mut Vec, path: &str, dir_append: &str) { - let songs = self.conn.listfiles(path).unwrap_or_default(); - for (i, s) in songs { - // Output of listfiles contains the last-modified thing, we dont want that - if i != "Last-Modified" { - if i == "directory" { - self.get_file_tree_into_vec(vec, &s, &s); - } else { - // We parse the string as float because the output of listfiles contains some random numbers, we dont want that - if !s.parse::().is_ok() { - let mut sam: String = String::new(); - sam.push_str(dir_append); - sam.push_str(r"/"); - sam.push_str(s.as_str()); - vec.push(sam); - } - } - } - } - } - - fn push(&mut self, song: Song) { - self.conn.push(song).unwrap(); - - } - - fn get_song(&self, filename: &str) -> Song { + fn get_song_with_only_filename(&self, filename: &str) -> Song { Song { file: filename.to_string(), artist: None, @@ -89,4 +76,54 @@ impl Connection { status.volume, status.repeat, status.random, status.single, status.consume ); } + + // Play controls + pub fn pause(&mut self) { + self.conn.pause(true).unwrap(); + } + + pub fn toggle_pause(&mut self) { + self.conn.toggle_pause().unwrap(); + } + + // Volume controls + pub fn inc_volume(&mut self, inc: i8) { + let cur = self.conn.status().unwrap().volume; + self.conn.volume(cur + inc).unwrap(); + } + + pub fn dec_volume(&mut self, dec: i8) { + let cur = self.conn.status().unwrap().volume; + self.conn.volume(cur - dec).unwrap(); + } +} + +fn get_file_tree_into_vec(conn: &mut Client, vec: &mut Vec, path: &str, dir_append: &str) { + let songs = conn.listfiles(path).unwrap_or_default(); + for (i, s) in songs { + // Output of listfiles contains the last-modified thing, we dont want that + if i != "Last-Modified" { + if i == "directory" { + get_file_tree_into_vec(conn, vec, &s, &s); + } else { + // We parse the string as float because the output of listfiles contains some random numbers, we dont want that + if !s.parse::().is_ok() { + let mut sam: String = String::new(); + sam.push_str(dir_append); + sam.push_str(r"/"); + sam.push_str(s.as_str()); + vec.push(sam); + } + } + } + } +} + +fn get_choice_index(ss: &Vec, selection: &str) -> usize { + let mut choice: usize = 0; + if let Some(index) = ss.iter().position(|s| s == selection) { + choice = index; + } + + choice } diff --git a/src/main.rs b/src/main.rs index 48db1ba..f58ce7d 100755 --- a/src/main.rs +++ b/src/main.rs @@ -5,29 +5,49 @@ use connection::Connection; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { - /// Ignore case in search + /// pause #[arg(short, long, default_value = "false")] pub pause: bool, + /// toggle pause #[arg(short, long, default_value = "false")] pub toggle_pause: bool, + /// show current status #[arg(short, long, default_value = "false")] pub show_status: bool, + /// use fzf selector for selecting songs #[arg(short, long, default_value = "false")] pub fzf_select: bool, + + /// use dmenu selector for selecting songss + #[arg(short, long, default_value = "false")] + pub dmenu_select: bool, } fn main() -> Result<(), Box> { let args = Args::parse(); let mut conn = Connection::new("127.0.0.1:6600")?; + if args.show_status { conn.status(); } + if args.toggle_pause { + conn.toggle_pause(); + } + + if args.pause { + conn.pause(); + } + if args.fzf_select { - conn.play_fzf() + conn.play_fzf(); + } + + if args.dmenu_select { + conn.play_dmenu(); } Ok(())