Added cpu temperature and battery

This commit is contained in:
mustafa salih 2021-01-09 04:06:01 +03:00
parent df3c059da4
commit 974563011c
11 changed files with 689 additions and 91 deletions

View File

@ -1,20 +0,0 @@
name: Rust
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: cargo build --verbose

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at mustafasalih1991@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

1
CONTRIBUTING.md Normal file
View File

@ -0,0 +1 @@
All Contributions are welcome.

371
Cargo.lock generated
View File

@ -1,11 +1,165 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "ahash"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
[[package]]
name = "alsa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"
dependencies = [
"alsa-sys",
"bitflags",
"libc",
"nix 0.15.0",
]
[[package]]
name = "alsa-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "async-channel"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-io"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
dependencies = [
"concurrent-queue",
"fastrand",
"futures-lite",
"libc",
"log",
"nb-connect",
"once_cell",
"parking",
"polling",
"vec-arena",
"waker-fn",
"winapi",
]
[[package]]
name = "async-net"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06de475c85affe184648202401d7622afb32f0f74e02192857d0201a16defbe5"
dependencies = [
"async-io",
"blocking",
"fastrand",
"futures-lite",
]
[[package]]
name = "async-task"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "blocking"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
dependencies = [
"async-channel",
"async-task",
"atomic-waker",
"fastrand",
"futures-lite",
"once_cell",
]
[[package]]
name = "breadx"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bff92e2ec549fe3f20386d73efb30263be7467463def0c2a780d7cee5dbf5e3"
dependencies = [
"async-io",
"async-net",
"blocking",
"bytemuck",
"cfg-if 1.0.0",
"cty",
"futures-lite",
"hashbrown",
"log",
"memchr",
"nix 0.19.1",
"ref_slice",
"tinyvec",
]
[[package]]
name = "bytemuck"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac"
[[package]]
name = "cache-padded"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
[[package]]
name = "cc"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.19" version = "0.4.19"
@ -19,6 +173,81 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "concurrent-queue"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
dependencies = [
"cache-padded",
]
[[package]]
name = "cty"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
[[package]]
name = "event-listener"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
[[package]]
name = "fastrand"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
dependencies = [
"instant",
]
[[package]]
name = "futures-core"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
[[package]]
name = "futures-io"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
[[package]]
name = "futures-lite"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
dependencies = [
"ahash",
]
[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.81" version = "0.2.81"
@ -31,12 +260,62 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]] [[package]]
name = "minreq" name = "minreq"
version = "2.2.1" version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2466d0a7e6bfcd54f69e4a17d4a4318985aaaf7fe3df4cd3b6f11ff551129ca3" checksum = "2466d0a7e6bfcd54f69e4a17d4a4318985aaaf7fe3df4cd3b6f11ff551129ca3"
[[package]]
name = "nb-connect"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "nix"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc",
"void",
]
[[package]]
name = "nix"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
dependencies = [
"bitflags",
"cc",
"cfg-if 1.0.0",
"libc",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.44" version = "0.1.44"
@ -57,11 +336,57 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rsblocks" name = "once_cell"
version = "0.1.3" version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "pin-project-lite"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "polling"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
dependencies = [ dependencies = [
"cfg-if 0.1.10",
"libc",
"log",
"wepoll-sys",
"winapi",
]
[[package]]
name = "ref_slice"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e1b7878800220a76a08f32c057829511440f65528b63b940f2f2bc145d7ac68"
[[package]]
name = "rsblocks"
version = "0.1.5"
dependencies = [
"alsa",
"breadx",
"chrono", "chrono",
"minreq", "minreq",
"nix 0.19.1",
"yaml-rust", "yaml-rust",
] ]
@ -76,12 +401,54 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "tinyvec"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "vec-arena"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "waker-fn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.0+wasi-snapshot-preview1" version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wepoll-sys"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rsblocks" name = "rsblocks"
version = "0.1.3" version = "0.1.5"
authors = ["mustafa salih <mustafasalih1991@gmail.com>"] authors = ["mustafa salih <mustafasalih1991@gmail.com>"]
edition = "2018" edition = "2018"
readme = "README.md" readme = "README.md"
@ -13,4 +13,10 @@ description = "a multi threaded status bar for dwm window manager for linux"
[dependencies] [dependencies]
chrono = "0.4" chrono = "0.4"
yaml-rust = "0.4" yaml-rust = "0.4"
minreq = "2.2.1" minreq = "2.2.1"
alsa = "0.4.3"
nix = "0.19.1"
[dependencies.breadx]
version = "0.1.11"
features = ["async"]

View File

@ -1,11 +1,11 @@
# rsblocks # rsblocks
[<img alt="github" src="https://img.shields.io/static/v1?label=github&message=rsblocks&color=acb0d0&logo=Github&style=flat-square&logoColor=a9b1d6" height="20">](https://github.com/MustafaSalih1993/rsblocks) [<img alt="github" src="https://img.shields.io/static/v1?label=github&message=rsblocks&color=acb0d0&logo=Github&style=flat-square&logoColor=a9b1d6" height="20">](https://github.com/MustafaSalih1993/rsblocks)
[<img alt="crates" src="https://img.shields.io/crates/v/rsblocks?logo=rust&logoColor=a9b1d6&style=flat-square&color=fc8d62" height="20">](https://crates.io/crates/rsblocks) [<img alt="crates" src="https://img.shields.io/crates/v/rsblocks?logo=rust&logoColor=a9b1d6&style=flat-square&color=fc8d62" height="20">](https://crates.io/crates/rsblocks)
[<img alt="build" src="https://img.shields.io/github/workflow/status/mustafasalih1993/rsblocks/Rust?color=b9f27c&logoColor=a9b1d6&style=flat-square" height="20">](https://github.com/MustafaSalih1993/rsblocks/actions?query=workflow%3ARust)
A multi threaded fast status bar for dwm window manager written in **Rust** 🦀 A multi threaded fast status bar for dwm window manager written in **Rust** 🦀
<p> <p>
<img align="center" src="./screenshots/1.png"/> <img align="center" src="./screenshots/2.png"/>
</p><br/> </p><br/>
## Features ## Features
@ -14,7 +14,9 @@ A multi threaded fast status bar for dwm window manager written in **Rust** 🦀
* Memory Usage * Memory Usage
* Disk Usage * Disk Usage
* Weather Temperature * Weather Temperature
* Sound volume _reads from `alsa-utils`_ * Sound Volume
* Battery Percentage
* Cpu Temperature
* Easy to configure with `rsblocks.yml` file * Easy to configure with `rsblocks.yml` file

View File

@ -27,9 +27,10 @@ disk:
# reads from alsa, alsa-utils package should # reads from alsa, alsa-utils package should
# be installed on the system to make it work. # be installed on the system to make it work.
volume: volume:
enable: false enable: true
icon: '' icon: ''
delay: 0.18 delay: 0.18
card: 'PULSE'
# weather format options is available on # weather format options is available on
@ -45,3 +46,15 @@ weather:
format: '%l:+%t' format: '%l:+%t'
delay: 7200.0 # 7200 seconds = 2 hours delay: 7200.0 # 7200 seconds = 2 hours
battery:
source: 'BAT0'
icon: ''
enable: false
delay: 120.0
cpu_temperature:
icon: ''
enable: true
delay: 120.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

BIN
screenshots/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -1,10 +1,10 @@
use alsa::mixer::{Mixer, SelemChannelId, SelemId};
use breadx::{display::*, window::Window};
use chrono::prelude::*; use chrono::prelude::*;
use minreq; use minreq;
use std::env;
use std::fs::File; use std::fs::File;
use std::io::Error; use std::io::Error;
use std::io::Read; use std::io::Read;
use std::process::Command;
use std::sync::mpsc; use std::sync::mpsc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -17,6 +17,8 @@ pub enum ThreadsData {
Memory(String), Memory(String),
Time(String), Time(String),
Weather(String), Weather(String),
Battery(String),
CpuTemp(String),
} }
#[derive(Clone)] #[derive(Clone)]
@ -27,6 +29,8 @@ pub struct Config {
pub disk: Disk, pub disk: Disk,
pub volume: Volume, pub volume: Volume,
pub weather: Weather, pub weather: Weather,
pub battery: Battery,
pub cpu_temperature: CpuTemp,
} }
#[derive(Clone)] #[derive(Clone)]
@ -54,6 +58,7 @@ pub struct Volume {
pub icon: String, pub icon: String,
pub enabled: bool, pub enabled: bool,
pub delay: f64, pub delay: f64,
pub card: String,
} }
#[derive(Clone)] #[derive(Clone)]
@ -65,17 +70,44 @@ pub struct Weather {
pub delay: f64, pub delay: f64,
} }
/* #[derive(Clone)]
// TODO: error handling required if rsblocks.yml file is empty pub struct Battery {
pub source: String,
pub icon: String,
pub enabled: bool,
pub delay: f64,
}
this function is responsible to check if the rsblocks.yml file #[derive(Clone)]
pub struct CpuTemp {
pub icon: String,
pub enabled: bool,
pub delay: f64,
}
/* TODOS
TODO 1: Error handling required if rsblocks.yml file is empty.
TODO 2: This lib file growing and soon it will be annoying to move
arround, need fix soon.
TODO 3: Need a better comments in code, or no one will understand what happens.
TODO 4: Need a documentation.
TODO 5: Fix repeated code for threads in `run` function.
*/
/*this function is responsible to check if the rsblocks.yml file
exists to call parse_config to read it OTHERWISE exists to call parse_config to read it OTHERWISE
it will call load_defaults to load a hardcoded default configuration it will call load_defaults to load a hardcoded default configuration
it will always return a valid configuration inside a Result. it will always return a valid configuration inside a Result.
*/ */
pub fn load_config() -> Result<Config, Error> { pub fn load_config() -> Result<Config, Error> {
let yml_source = env::var("HOME").unwrap() + "/.config/rsblocks/rsblocks.yml"; let yml_source = std::env::var("HOME").unwrap() + "/.config/rsblocks/rsblocks.yml";
let mut data = String::new(); let mut data = String::new();
let mut file = match File::open(&yml_source) { let mut file = match File::open(&yml_source) {
Ok(file) => file, Ok(file) => file,
@ -115,6 +147,7 @@ fn load_defaults() -> Config {
icon: String::from(""), icon: String::from(""),
enabled: false, enabled: false,
delay: 0.17, delay: 0.17,
card: String::from("ALSA"),
}, },
weather: Weather { weather: Weather {
city: String::from(""), city: String::from(""),
@ -123,6 +156,17 @@ fn load_defaults() -> Config {
enabled: false, enabled: false,
delay: 7200.0, //7200 seconds = 2 hours delay: 7200.0, //7200 seconds = 2 hours
}, },
battery: Battery {
source: String::from("BAT0"),
icon: String::from(""),
enabled: false,
delay: 120.0,
},
cpu_temperature: CpuTemp {
icon: String::from(""),
enabled: false,
delay: 120.0,
},
} }
} }
@ -139,6 +183,8 @@ fn parse_config(doc: &yaml::Yaml) -> Config {
let disk_icon = get_or_set_string(doc, "disk", "icon", ""); let disk_icon = get_or_set_string(doc, "disk", "icon", "");
let volume_icon = get_or_set_string(doc, "volume", "icon", ""); let volume_icon = get_or_set_string(doc, "volume", "icon", "");
let weather_icon = get_or_set_string(doc, "weather", "icon", ""); let weather_icon = get_or_set_string(doc, "weather", "icon", "");
let battery_icon = get_or_set_string(doc, "battery", "icon", "");
let cpu_temperature_icon = get_or_set_string(doc, "cpu_temperature", "icon", "");
//parsing formats and city weather //parsing formats and city weather
let time_format = get_or_set_string(doc, "time", "format", "%T"); let time_format = get_or_set_string(doc, "time", "format", "%T");
@ -150,13 +196,23 @@ fn parse_config(doc: &yaml::Yaml) -> Config {
let memory_enabled = get_or_set_bool(doc, "memory", "enable"); let memory_enabled = get_or_set_bool(doc, "memory", "enable");
let volume_enabled = get_or_set_bool(doc, "volume", "enable"); let volume_enabled = get_or_set_bool(doc, "volume", "enable");
let weather_enabled = get_or_set_bool(doc, "weather", "enable"); let weather_enabled = get_or_set_bool(doc, "weather", "enable");
let battery_enabled = get_or_set_bool(doc, "battery", "enable");
let cpu_temperature_enabled = get_or_set_bool(doc, "cpu_temperature", "enable");
// parsing update_delay state (should be all seconds in f64 type) // parsing update_delay state (should be all seconds in f64 type)
let time_delay = get_or_set_f32(doc, "time", "delay", 1.0); let time_delay = get_or_set_f64(doc, "time", "delay", 1.0);
let disk_delay = get_or_set_f32(doc, "disk", "delay", 120.0); let disk_delay = get_or_set_f64(doc, "disk", "delay", 120.0);
let memory_delay = get_or_set_f32(doc, "memory", "delay", 2.0); let memory_delay = get_or_set_f64(doc, "memory", "delay", 2.0);
let volume_delay = get_or_set_f32(doc, "volume", "delay", 0.17); let volume_delay = get_or_set_f64(doc, "volume", "delay", 0.17);
let weather_delay = get_or_set_f32(doc, "weather", "delay", 7200.0); let weather_delay = get_or_set_f64(doc, "weather", "delay", 7200.0);
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);
// parsing card for volume, ALSA or PULSE
let volume_card = get_or_set_string(doc, "volume", "card", "ALSA");
// parsing battery source name
let battery_source = get_or_set_string(doc, "battery", "source", "BAT0");
Config { Config {
seperator, seperator,
@ -179,6 +235,7 @@ fn parse_config(doc: &yaml::Yaml) -> Config {
icon: volume_icon, icon: volume_icon,
enabled: volume_enabled, enabled: volume_enabled,
delay: volume_delay, delay: volume_delay,
card: volume_card,
}, },
weather: Weather { weather: Weather {
city: weather_city, city: weather_city,
@ -187,11 +244,22 @@ fn parse_config(doc: &yaml::Yaml) -> Config {
enabled: weather_enabled, enabled: weather_enabled,
delay: weather_delay, delay: weather_delay,
}, },
battery: Battery {
source: battery_source,
icon: battery_icon,
enabled: battery_enabled,
delay: battery_delay,
},
cpu_temperature: CpuTemp {
icon: cpu_temperature_icon,
enabled: cpu_temperature_enabled,
delay: cpu_temperature_delay,
},
} }
} }
// getting a f32 value from rsblocks.yml file or set default (last argument) // getting a f32 value from rsblocks.yml file or set default (last argument)
fn get_or_set_f32(doc: &yaml::Yaml, parent: &str, child: &str, default: f64) -> f64 { fn get_or_set_f64(doc: &yaml::Yaml, parent: &str, child: &str, default: f64) -> f64 {
let val: f64 = if doc[parent][child].is_badvalue() { let val: f64 = if doc[parent][child].is_badvalue() {
default default
} else { } else {
@ -227,20 +295,30 @@ fn get_or_set_string(doc: &yaml::Yaml, parent: &str, child: &str, default_val: &
*/ */
/* Running the program: // Running the program:
TODO: this is sucks, repeated code in threads below, fix me you fucking asshole
*/
pub fn run(config: Config) { pub struct Blocks {
disp: Display<name::NameConnection>,
root: Window,
}
impl Blocks {
pub fn new() -> Self {
let disp = Display::create(None, None).expect("Failed to create x11 connection");
let root = disp.default_screen().root;
Self { disp, root }
}
}
pub fn run(config: Config, mut blocks: Blocks) {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
// volume thread // volume thread
if config.volume.enabled { if config.volume.enabled {
let volume_tx = tx.clone(); let volume_tx = tx.clone();
let configcp = config.clone(); let configcp = config.clone();
let mut vol_data = ThreadsData::Sound(get_volume(&configcp)); let mut vol_data = ThreadsData::Sound(get_volume(&configcp));
thread::spawn(move || loop { thread::spawn(move || loop {
let _ = volume_tx.send(vol_data); volume_tx.send(vol_data).unwrap();
vol_data = ThreadsData::Sound(get_volume(&configcp)); vol_data = ThreadsData::Sound(get_volume(&configcp));
thread::sleep(Duration::from_secs_f64(configcp.volume.delay)) thread::sleep(Duration::from_secs_f64(configcp.volume.delay))
}); });
@ -284,6 +362,32 @@ pub fn run(config: Config) {
}); });
} }
// Battery thread
if config.battery.enabled {
let battery_tx = tx.clone();
let configcp = config.clone();
let battery_data = get_battery(&configcp).unwrap();
let mut battery_data = ThreadsData::Battery(battery_data);
thread::spawn(move || loop {
battery_tx.send(battery_data).unwrap();
battery_data = ThreadsData::Battery(get_battery(&configcp).unwrap());
thread::sleep(Duration::from_secs_f64(configcp.battery.delay))
});
}
// Cpu temperature thread
if config.cpu_temperature.enabled {
let cpu_temp_tx = tx.clone();
let configcp = config.clone();
let cpu_temp_data = get_cpu_temp(&configcp).unwrap();
let mut cpu_temp_data = ThreadsData::CpuTemp(cpu_temp_data);
thread::spawn(move || loop {
cpu_temp_tx.send(cpu_temp_data).unwrap();
cpu_temp_data = ThreadsData::CpuTemp(get_cpu_temp(&configcp).unwrap());
thread::sleep(Duration::from_secs_f64(configcp.cpu_temperature.delay))
});
}
// Time thread // Time thread
{ {
let time_tx = tx; let time_tx = tx;
@ -299,8 +403,7 @@ pub fn run(config: Config) {
//Main //Main
{ {
// NOTE: order matters to the final format // NOTE: order matters to the final format
let mut bar: Vec<String> = vec!["".to_string(); 7];
let mut bar: Vec<String> = vec!["".to_string(); 5];
//iterating the values recieved from the threads //iterating the values recieved from the threads
for data in rx { for data in rx {
match data { match data {
@ -308,29 +411,28 @@ pub fn run(config: Config) {
ThreadsData::Weather(x) => bar[1] = x, ThreadsData::Weather(x) => bar[1] = x,
ThreadsData::Disk(x) => bar[2] = x, ThreadsData::Disk(x) => bar[2] = x,
ThreadsData::Memory(x) => bar[3] = x, ThreadsData::Memory(x) => bar[3] = x,
ThreadsData::Time(x) => bar[4] = x, ThreadsData::CpuTemp(x) => bar[4] = x,
ThreadsData::Battery(x) => bar[5] = x,
ThreadsData::Time(x) => bar[6] = x,
} }
// match ends here // match ends here
update(&bar); update(&bar, &mut blocks);
} }
} }
} }
/* pub fn update(bar: &Vec<String>, blocks: &mut Blocks) {
this will call the command 'xsetroot -name <the arg>'
*/
pub fn update(bar: &Vec<String>) {
// TODO: FIX ME, this solution sucks // TODO: FIX ME, this solution sucks
let mut x = String::new(); let mut x = String::new();
for i in bar.iter() { for i in bar.iter() {
x.push_str(i.as_str()); x.push_str(i.as_str());
} }
Command::new("xsetroot")
.arg("-name") blocks
.arg(x) .root
.output() .set_title(&mut blocks.disp, &x)
.unwrap(); .expect("Failed to set title of root");
} }
/*############################ RUNNING THE PROGRAM ENDS HERE ###########################################*/ /*############################ RUNNING THE PROGRAM ENDS HERE ###########################################*/
@ -378,48 +480,49 @@ fn get_weather(config: &Config) -> String {
format!(" {} {} {}", config.weather.icon, res, config.seperator) format!(" {} {} {}", config.weather.icon, res, config.seperator)
} }
// getting disk usage
pub fn get_disk(config: &Config) -> String { pub fn get_disk(config: &Config) -> String {
let cmd = Command::new("sh") const GB: u64 = (1024 * 1024) * 1024;
.arg("-c") let statvfs = nix::sys::statvfs::statvfs("/").unwrap();
.args(&["df -h"])
.output()
.unwrap();
let output = String::from_utf8_lossy(&cmd.stdout);
let mut disk_used = String::new(); let mut disk_used = String::new();
for line in output.lines() {
if line.ends_with('/') { let total = (statvfs.blocks() * statvfs.fragment_size()) / GB;
let splited = line.split_whitespace().collect::<Vec<&str>>(); let available = (statvfs.blocks_free() * statvfs.fragment_size()) / GB;
disk_used = splited[2].to_string(); let used = total - available;
break;
} disk_used.push_str(&format!("{}G", used));
}
format!( format!(
" {} {} {}", " {} {} {}",
config.disk.icon, disk_used, config.seperator config.disk.icon, disk_used, config.seperator
) )
} }
// FIX ME: what a horrible solution to get the sound, i dont like it
// find another way
pub fn get_volume(config: &Config) -> String { pub fn get_volume(config: &Config) -> String {
let cmd_content = Command::new("amixer") let card = if config.volume.card == "PULSE" {
.args(&["-D", "pulse", "get", "Master"]) "pulse"
.output() } else {
.expect("Make sure that you have alsa-utils installed on your system"); "default"
};
let vol: String = String::from_utf8_lossy(&cmd_content.stdout) let mixer = Mixer::new(card, false).expect("Failed to open mixer");
.lines() let selem_id = SelemId::new("Master", 0);
.last() let selem = mixer.find_selem(&selem_id).expect("Couldn't find selem");
.expect("failed to get sound volume") let selem_chan_id = SelemChannelId::FrontLeft;
.split('[')
.collect::<Vec<&str>>()[1]
.split(']')
.collect::<Vec<&str>>()[0]
.trim()
.to_string();
format!(" {} {} {}", config.volume.icon, vol, config.seperator) let (min, max) = selem.get_playback_volume_range();
let mut raw_volume = selem
.get_playback_volume(selem_chan_id)
.expect("Failed to get raw_volume");
let range = max - min;
let vol = if range == 0 {
0
} else {
raw_volume -= min;
((raw_volume as f64 / range as f64) * 100.) as u64
};
format!(" {} {}% {}", config.volume.icon, vol, config.seperator)
} }
/* /*
@ -503,3 +606,52 @@ fn assign_val(line: &str, assignable: &mut u32) {
.unwrap(); .unwrap();
*assignable = parsed; *assignable = parsed;
} }
// getting battery percentage
pub fn get_battery(config: &Config) -> Result<String, Error> {
let battery_full_cap_file = format!(
"/sys/class/power_supply/{}/charge_full_design",
config.battery.source
);
let battery_charge_now_file = format!(
"/sys/class/power_supply/{}/charge_now",
config.battery.source
);
let mut buf = String::new();
// FIXME: ugly error handling AGAIN fixing later, im lazy
match File::open(&battery_full_cap_file) {
Ok(mut file) => file.read_to_string(&mut buf)?,
Err(_) => return Ok(String::from("check your battery source name")),
};
let full_design = buf.trim().parse::<u32>().unwrap();
buf.clear();
// NOTE: no need to error check if passed the above match
File::open(&battery_charge_now_file)?.read_to_string(&mut buf)?;
let charge_now = buf.trim().parse::<u32>().unwrap();
let battery_percentage = (charge_now as f32 / full_design as f32) * 100.0;
let result = format!(
" {} {:.0}% {}",
config.battery.icon, battery_percentage, config.seperator
);
Ok(result)
}
// getting cpu temperature
pub fn get_cpu_temp(config: &Config) -> Result<String, std::io::Error> {
let mut buf = String::new();
File::open("/sys/class/thermal/thermal_zone0/temp")?.read_to_string(&mut buf)?;
let value = buf.trim().parse::<f32>().unwrap();
let result = format!(
" {} {}° {}",
config.cpu_temperature.icon,
value / 1000.0,
config.seperator
);
Ok(result)
}

View File

@ -2,5 +2,6 @@ use rsblocks;
fn main() { fn main() {
let config = rsblocks::load_config().unwrap(); let config = rsblocks::load_config().unwrap();
rsblocks::run(config); let blocks = rsblocks::Blocks::new();
rsblocks::run(config, blocks);
} }