summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod5
-rw-r--r--go.sum2
-rw-r--r--statusbar.conf15
-rw-r--r--statusbar.go193
4 files changed, 215 insertions, 0 deletions
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..65bb318
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module statusbar
+
+go 1.14
+
+require github.com/BurntSushi/toml v0.3.1 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..9cb2df8
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
diff --git a/statusbar.conf b/statusbar.conf
new file mode 100644
index 0000000..dc46741
--- /dev/null
+++ b/statusbar.conf
@@ -0,0 +1,15 @@
+separator = " | "
+
+[ip]
+label = "IP: "
+interfaces = [ "eno1" ]
+ipv4only = true
+
+[mounts]
+label = "mounts: "
+mountpoints = [ "/", "/mnt/storage", "/mnt/storage1" ]
+
+[music]
+labelplaying = "▶ "
+labelpaused = "⏸ "
+labelstopped = "-"
diff --git a/statusbar.go b/statusbar.go
new file mode 100644
index 0000000..607b545
--- /dev/null
+++ b/statusbar.go
@@ -0,0 +1,193 @@
+package main
+
+import (
+ "fmt"
+ "net"
+ "syscall"
+ "strings"
+ "strconv"
+ "os"
+ "os/exec"
+ "io/ioutil"
+ "time"
+
+ "github.com/BurntSushi/toml"
+)
+
+type Config struct {
+ Separator string
+ IP IPConfig
+ Mounts MountConfig
+ Music MusicConfig
+}
+
+type IPConfig struct {
+ Label string
+ Interfaces []string
+ IPv4Only bool `toml:"ipv4only"`
+}
+
+type MountConfig struct {
+ Label string
+ MountPoints []string `toml:"mountpoints"`
+}
+
+type MusicConfig struct {
+ LabelPlaying string `toml:"labelplaying"`
+ LabelPaused string `toml:"labelpaused"`
+ LabelStopped string `toml:"labelstopped"`
+}
+
+func diskSizes(mounts []string) string {
+ var b strings.Builder
+ var statfs syscall.Statfs_t
+ const div = float64(1024 * 1024 * 1024)
+ const unit = "G"
+ sep := ""
+ for _, mount := range mounts {
+ b.WriteString(sep)
+ err := syscall.Statfs(mount, &statfs)
+ if err != nil {
+ panic(err)
+ }
+ availBytes := float64(statfs.Bavail * uint64(statfs.Bsize))
+ avail := strconv.FormatFloat(availBytes / div, 'f', 2, 64)
+ b.WriteString(fmt.Sprintf("%v : %v %v", mount, avail, unit))
+ sep = " "
+ }
+ return b.String()
+}
+
+func ips(interfaces []string, IPv4Only bool) string {
+ var b strings.Builder
+ sep := ""
+ for _, interfaceName := range interfaces {
+ b.WriteString(sep)
+ b.WriteString(interfaceName)
+ b.WriteString(": ")
+ if len(interfaces) > 1 {
+ b.WriteString(" [")
+ }
+ b.WriteString(ip(interfaceName, IPv4Only))
+ if len(interfaces) > 1 {
+ b.WriteString(" ]")
+ }
+ sep = " "
+ }
+ return b.String()
+}
+
+func ip(interfaceName string, IPv4Only bool) string {
+ var b strings.Builder
+ sep := ""
+ in, err := net.InterfaceByName(interfaceName)
+ if err != nil {
+ panic(err)
+ }
+ addrs, err := in.Addrs()
+ if err != nil {
+ panic(err)
+ }
+ for _, addr := range addrs {
+ var ip net.IP
+ switch v := addr.(type) {
+ case *net.IPAddr:
+ ip = v.IP
+ case *net.IPNet:
+ ip = v.IP
+ default:
+ }
+ if IPv4Only {
+ if ip.To4() != nil {
+ b.WriteString(ip.String())
+ b.WriteString(sep)
+ sep = " "
+ }
+ } else {
+ b.WriteString(sep)
+ b.WriteString(ip.String())
+ sep = " "
+ }
+ }
+ return b.String()
+}
+
+func clock() string {
+ t := time.Now()
+ return t.Format("Monday 2006-01-02 15:04:05")
+}
+
+func nowPlayingMPD() string {
+ cmd := exec.Command("mpc", "current")
+ out, err := cmd.Output()
+ if err != nil {
+ panic(err)
+ }
+ sOut := string(out)
+ sOut = strings.ReplaceAll(sOut, "\n", "")
+ return sOut
+}
+
+// Returns 0 if playing, 1 if paused and 2 if stopped
+func statusMPD() int {
+ cmd := exec.Command("mpc", "status")
+ out, err := cmd.Output()
+ if err != nil {
+ panic(err)
+ }
+ sOut := string(out)
+ if strings.Contains(sOut, "playing") {
+ return 0
+ } else if strings.Contains(sOut, "paused") {
+ return 1
+ } else {
+ return 2
+ }
+}
+
+func main() {
+ var configPath = "/etc/statusbar.conf"
+ var content []byte
+ var err error
+ if _, err := os.Stat(configPath); err != nil {
+ content, err = ioutil.ReadAll(os.Stdin)
+ } else {
+ content, err = ioutil.ReadFile(configPath)
+ }
+ if err != nil {
+ panic(err)
+ }
+ var config Config
+ _, err = toml.Decode(string(content), &config)
+ if err != nil {
+ panic(err)
+ }
+ for true {
+ var b strings.Builder
+ switch statusMPD() {
+ case 0:
+ b.WriteString(config.Music.LabelPlaying)
+ case 1:
+ b.WriteString(config.Music.LabelPaused)
+ case 2:
+ b.WriteString(config.Music.LabelStopped)
+ default:
+ b.WriteString("Unknown MPD status")
+ }
+ b.WriteString(nowPlayingMPD())
+ b.WriteString(config.Separator)
+ b.WriteString(config.IP.Label)
+ b.WriteString("[ ")
+ b.WriteString(ips(config.IP.Interfaces, config.IP.IPv4Only))
+ b.WriteString(" ]")
+ b.WriteString(config.Separator)
+ b.WriteString(config.Mounts.Label)
+ b.WriteString("[ ")
+ b.WriteString(diskSizes(config.Mounts.MountPoints))
+ b.WriteString(" ]")
+ b.WriteString(config.Separator)
+ b.WriteString(clock())
+ fmt.Println(b.String())
+ time.Sleep(10 * time.Second)
+ }
+}