statusbar-go/statusbar.go

145 lines
3.3 KiB
Go

package main
import (
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
func main() {
update := make(chan bool, 1)
var err error // so assigning the global works
CONN, err = init_connections()
if err != nil {
warn("Failed to connect to required buses!", err)
return
}
defer CONN.close_all()
go dbus_session_handler(update)
go dbus_system_handler(update)
go pulseaudio_handler(update)
go signal_handler(update)
go time_handler(update)
go sway_input_handler(update)
output := produce_output()
fmt.Println(output)
for range update {
previous := output
output = produce_output()
if output != previous {
fmt.Println(output)
}
}
}
func warn(message string, err error) (int, error) {
return os.Stderr.WriteString(fmt.Sprintf("Warning: %s\n%s\n", message, err.Error()))
}
func format_stat(input []byte) string {
return strings.TrimSuffix(string(input), "\n")
}
func produce_output() string {
var output strings.Builder
// add currently tracked toggl project
toggl := getC(&CACHE, CACHE_TOGGL, get_current_toggl_project)
output.WriteString(toggl)
output.WriteString(SEPARATOR)
// add playing Spotify song
media := getC(&CACHE, CACHE_MEDIA, get_playing_spotify_media)
if media != "" {
output.WriteString(media)
output.WriteString(SEPARATOR)
}
// add BT headset status
bt_connected := getC(&CACHE, CACHE_BT_CONNECTED, get_bt_headset_connected)
if bt_connected {
output.WriteString("BT headset")
bt_battery := getC(&CACHE, CACHE_BT_BATTERY, get_bt_headset_battery)
if bt_battery != "" {
output.WriteString(": ")
output.WriteString(bt_battery)
output.WriteRune('%')
}
output.WriteString(SEPARATOR)
}
// add volume
vol, muted := get_default_sink_volume()
output.WriteString(fmt.Sprintf("Vol: %d%%", vol))
if muted {
output.WriteString(" [M]")
}
// add battery
batCap, err := os.ReadFile("/sys/class/power_supply/" + BATTERY + "/capacity")
if err != nil {
warn("Failed to read battery capacity!", err)
} else {
batStat, err := os.ReadFile("/sys/class/power_supply/" + BATTERY + "/status")
if err != nil {
warn("Failed to read battery status!", err)
} else {
output.WriteString(SEPARATOR)
output.WriteString(format_stat(batCap))
output.WriteString("% ")
output.WriteString(format_stat(batStat))
}
}
// add keyboard layout
layout := getC(&CACHE, CACHE_LAYOUT, get_current_layout)
output.WriteString(SEPARATOR)
output.WriteString(long_layout_to_short(layout))
// add time
output.WriteString(SEPARATOR)
dt := time.Now()
output.WriteString(dt.Format("Mon 2006-01-02 15:04"))
return output.String()
}
func signal_handler(feedback chan bool) {
// SIGUSR1 can be sent to manually trigger a reprint
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGUSR1)
for range sigs {
// delete all cache
CACHE.Range(func(key, _ interface{}) bool {
CACHE.Delete(key)
return true
})
feedback <- true
}
}
func time_handler(feedback chan bool) {
// sleep until the clock hits the next minute
dt := time.Now()
time.Sleep(time.Duration(60-dt.Second()) * time.Second)
CACHE.Delete(CACHE_BT_BATTERY) // think of a better way to do this
CACHE.Delete(CACHE_TOGGL)
feedback <- true
for {
// update the time every 60 seconds
CACHE.Delete(CACHE_BT_BATTERY)
CACHE.Delete(CACHE_TOGGL)
time.Sleep(60 * time.Second)
feedback <- true
}
}