diff --git a/Cargo.lock b/Cargo.lock index a6681e8..a168dae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "bufstream" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" + [[package]] name = "bytemuck" version = "1.4.1" @@ -281,6 +287,17 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2466d0a7e6bfcd54f69e4a17d4a4318985aaaf7fe3df4cd3b6f11ff551129ca3" +[[package]] +name = "mpd" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a20784da57fa01bf7910a5da686d9f39ff37feaa774856b71f050e4331bf82" +dependencies = [ + "bufstream", + "rustc-serialize", + "time", +] + [[package]] name = "nb-connect" version = "1.0.2" @@ -380,16 +397,23 @@ checksum = "4e1b7878800220a76a08f32c057829511440f65528b63b940f2f2bc145d7ac68" [[package]] name = "rsblocks" -version = "0.1.5" +version = "0.1.6" dependencies = [ "alsa", "breadx", "chrono", "minreq", + "mpd", "nix 0.19.1", "yaml-rust", ] +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "time" version = "0.1.44" diff --git a/Cargo.toml b/Cargo.toml index ef392be..1c7f856 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsblocks" -version = "0.1.5" +version = "0.1.6" authors = ["mustafa salih "] edition = "2018" readme = "README.md" @@ -16,6 +16,7 @@ yaml-rust = "0.4" minreq = "2.2.1" alsa = "0.4.3" nix = "0.19.1" +mpd = "0.0.12" [dependencies.breadx] version = "0.1.11" diff --git a/README.md b/README.md index 7f137a1..2b5350e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A multi threaded fast status bar for dwm window manager written in **Rust** 🦀

- +


## Features @@ -18,6 +18,7 @@ A multi threaded fast status bar for dwm window manager written in **Rust** 🦀 * Battery Percentage * Cpu Temperature * Uptime +* Mpd Current Song File * Easy to configure with `rsblocks.yml` file diff --git a/rsblocks.yml b/rsblocks.yml index 6d0786c..059016a 100644 --- a/rsblocks.yml +++ b/rsblocks.yml @@ -24,6 +24,27 @@ disk: delay: 120.0 +battery: + source: 'BAT0' + icon: '' + enable: false + delay: 120.0 + + +cpu_temperature: + icon: '' + enable: true + delay: 120.0 + + +mpd: + icon: '' + host: '127.0.0.1' + port: '6600' + enable: false + delay: 5.0 + + # reads from alsa, alsa-utils package should # be installed on the system to make it work. volume: @@ -45,16 +66,3 @@ weather: city: '' format: '%l:+%t' delay: 7200.0 # 7200 seconds = 2 hours - - -battery: - source: 'BAT0' - icon: '' - enable: false - delay: 120.0 - - -cpu_temperature: - icon: '' - enable: true - delay: 120.0 diff --git a/screenshots/1.png b/screenshots/1.png new file mode 100644 index 0000000..2715a31 Binary files /dev/null and b/screenshots/1.png differ diff --git a/screenshots/2.png b/screenshots/2.png deleted file mode 100644 index 958332e..0000000 Binary files a/screenshots/2.png and /dev/null differ diff --git a/src/lib.rs b/src/lib.rs index c690414..12a053e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use alsa::mixer::{Mixer, SelemChannelId, SelemId}; use breadx::{display::*, window::Window}; use chrono::prelude::*; +use mpd::{Client, Song}; use std::fs::File; use std::io::Error; use std::io::Read; @@ -11,6 +12,7 @@ use yaml_rust::{yaml, YamlLoader}; #[derive(Debug)] pub enum ThreadsData { + Mpd(String), Sound(String), Disk(String), Memory(String), @@ -32,6 +34,7 @@ pub struct Config { pub battery: Battery, pub cpu_temperature: CpuTemp, pub uptime: Uptime, + pub mpd: Mpd, } #[derive(Clone)] @@ -92,6 +95,15 @@ pub struct Uptime { pub enabled: bool, pub delay: f64, } + +#[derive(Clone)] +pub struct Mpd { + pub icon: String, + pub host: String, + pub port: String, + pub enabled: bool, + pub delay: f64, +} /* TODOS TODO 1: Error handling required if rsblocks.yml file is empty. @@ -105,6 +117,8 @@ pub struct Uptime { TODO 5: Fix repeated code for threads in `run` function. + TODO 6: Getting song metadata from mpd by a format provided by the user. + */ /*this function is responsible to check if the rsblocks.yml file @@ -179,6 +193,13 @@ fn load_defaults() -> Config { enabled: false, delay: 60.0, }, + mpd: Mpd { + icon: String::from(""), + host: String::from("127.0.0.1"), + port: String::from("6600"), + enabled: false, + delay: 15.0, + }, } } @@ -198,6 +219,7 @@ fn parse_config(doc: &yaml::Yaml) -> Config { let battery_icon = get_or_set_string(doc, "battery", "icon", ""); let cpu_temperature_icon = get_or_set_string(doc, "cpu_temperature", "icon", ""); let uptime_icon = get_or_set_string(doc, "uptime", "icon", ""); + let mpd_icon = get_or_set_string(doc, "mpd", "icon", ""); //parsing formats and city weather let time_format = get_or_set_string(doc, "time", "format", "%T"); @@ -212,6 +234,7 @@ fn parse_config(doc: &yaml::Yaml) -> Config { let battery_enabled = get_or_set_bool(doc, "battery", "enable"); let cpu_temperature_enabled = get_or_set_bool(doc, "cpu_temperature", "enable"); let uptime_enabled = get_or_set_bool(doc, "uptime", "enable"); + let mpd_enabled = get_or_set_bool(doc, "mpd", "enable"); // parsing update_delay state (should be all seconds in f64 type) let time_delay = get_or_set_f64(doc, "time", "delay", 1.0); @@ -222,6 +245,7 @@ fn parse_config(doc: &yaml::Yaml) -> Config { let battery_delay = get_or_set_f64(doc, "battery", "delay", 120.0); let cpu_temperature_delay = get_or_set_f64(doc, "cpu_temperature", "delay", 120.0); let uptime_delay = get_or_set_f64(doc, "uptime", "delay", 60.0); + let mpd_delay = get_or_set_f64(doc, "mpd", "delay", 15.0); // parsing card for volume, ALSA or PULSE let volume_card = get_or_set_string(doc, "volume", "card", "ALSA"); @@ -229,6 +253,10 @@ fn parse_config(doc: &yaml::Yaml) -> Config { // parsing battery source name let battery_source = get_or_set_string(doc, "battery", "source", "BAT0"); + //parsing mpd host and port + let mpd_host = get_or_set_string(doc, "mpd", "host", "127.0.0.1"); + let mpd_port = get_or_set_string(doc, "mpd", "port", "6600"); + Config { seperator, time: Time { @@ -275,6 +303,13 @@ fn parse_config(doc: &yaml::Yaml) -> Config { enabled: uptime_enabled, delay: uptime_delay, }, + mpd: Mpd { + icon: mpd_icon, + host: mpd_host, + port: mpd_port, + enabled: mpd_enabled, + delay: mpd_delay, + }, } } @@ -338,6 +373,19 @@ impl Default for Blocks { pub fn run(config: Config, mut blocks: Blocks) { let (tx, rx) = mpsc::channel(); + + // mpd thread + if config.mpd.enabled { + let mpd_tx = tx.clone(); + let configcp = config.clone(); + let mut mpd_data = ThreadsData::Mpd(get_mpd_current(&configcp)); + thread::spawn(move || loop { + mpd_tx.send(mpd_data).unwrap(); + mpd_data = ThreadsData::Mpd(get_mpd_current(&configcp)); + thread::sleep(Duration::from_secs_f64(configcp.mpd.delay)) + }); + } + // volume thread if config.volume.enabled { let volume_tx = tx.clone(); @@ -441,18 +489,19 @@ pub fn run(config: Config, mut blocks: Blocks) { //Main { // NOTE: order matters to the final format - let mut bar: Vec = vec!["".to_string(); 8]; + let mut bar: Vec = vec!["".to_string(); 9]; //iterating the values recieved from the threads for data in rx { match data { - ThreadsData::Sound(x) => bar[0] = x, - ThreadsData::Weather(x) => bar[1] = x, - ThreadsData::Disk(x) => bar[2] = x, - ThreadsData::Memory(x) => bar[3] = x, - ThreadsData::CpuTemp(x) => bar[4] = x, - ThreadsData::Battery(x) => bar[5] = x, - ThreadsData::Uptime(x) => bar[6] = x, - ThreadsData::Time(x) => bar[7] = x, + ThreadsData::Mpd(x) => bar[0] = x, + ThreadsData::Sound(x) => bar[1] = x, + ThreadsData::Weather(x) => bar[2] = x, + ThreadsData::Disk(x) => bar[3] = x, + ThreadsData::Memory(x) => bar[4] = x, + ThreadsData::CpuTemp(x) => bar[5] = x, + ThreadsData::Battery(x) => bar[6] = x, + ThreadsData::Uptime(x) => bar[7] = x, + ThreadsData::Time(x) => bar[8] = x, } // match ends here @@ -713,3 +762,21 @@ pub fn get_uptime(config: &Config) -> Result { let result = format!(" {} {} {}", config.uptime.icon, uptime, config.seperator); Ok(result) } + +// getting mpd song file +pub fn get_mpd_current(config: &Config) -> String { + let stream_path = format!("{}:{}", config.mpd.host, config.mpd.port); + let mut conn = match Client::connect(&stream_path) { + Ok(connection) => connection, + _ => return String::from(""), + }; + conn.volume(100).unwrap(); + let current: Song = conn.currentsong().unwrap().unwrap(); + + let result = format!( + " {} {} {}", + config.mpd.icon, current.file, config.seperator + ); + + result +}