statusbar-go/module_dbus.go
2024-10-30 15:42:14 +02:00

208 lines
4.8 KiB
Go

package main
import (
"fmt"
"html"
"strconv"
"strings"
"github.com/godbus/dbus/v5"
)
var HEADSET_PATH = dbus.ObjectPath("/org/bluez/hci0/dev_" + strings.ReplaceAll(HEADSET, ":", "_"))
func dbus_system_handler(feedback chan bool) {
// watches for BT headset connections
headsetObjectPath := "/org/bluez/hci0/dev_" + strings.ReplaceAll(HEADSET, ":", "_")
err := CONN.dbusSystem.AddMatchSignal(
dbus.WithMatchObjectPath(dbus.ObjectPath(headsetObjectPath)),
dbus.WithMatchInterface("org.freedesktop.DBus.Properties"),
)
if err != nil {
warn("Failed to add match signal", err)
return
}
sigs := make(chan *dbus.Signal, 100)
CONN.dbusSystem.Signal(sigs)
for range sigs {
CACHE.Delete(CACHE_BT_CONNECTED)
CACHE.Delete(CACHE_BT_BATTERY)
feedback <- true
}
}
func dbus_session_handler(feedback chan bool) {
// watches for media changes
err := CONN.dbusSession.AddMatchSignal(
dbus.WithMatchObjectPath("/org/mpris/MediaPlayer2"),
dbus.WithMatchInterface("org.freedesktop.DBus.Properties"),
)
if err != nil {
warn("Failed to add match signal", err)
return
}
sigs := make(chan *dbus.Signal, 100)
CONN.dbusSession.Signal(sigs)
for range sigs {
CACHE.Delete(CACHE_MEDIA)
feedback <- true
}
}
func get_bt_headset_connected() bool {
obj := CONN.dbusSystem.Object("org.bluez", HEADSET_PATH)
status, err := obj.GetProperty("org.bluez.Device1.Connected")
if err == nil {
if status.String() == "true" {
return true
}
}
return false
}
func get_bt_headset_battery() string {
obj := CONN.dbusSystem.Object("org.bluez", HEADSET_PATH)
status, err := obj.GetProperty("org.bluez.Battery1.Percentage")
if err == nil {
return fmt.Sprintf("%v", status.Value())
}
return ""
}
func get_playing_spotify_media() string {
var output strings.Builder
obj := CONN.dbusSession.Object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
metadata, err := obj.GetProperty("org.mpris.MediaPlayer2.Player.Metadata")
if err != nil {
return ""
}
status, err := obj.GetProperty("org.mpris.MediaPlayer2.Player.PlaybackStatus")
if err != nil {
return ""
}
if status.String() != "\"Playing\"" {
output.WriteString("‖ ")
}
metadataMap := metadata.Value().(map[string]dbus.Variant)
artists := make([]string, 100)
metadataMap["xesam:artist"].Store(&artists)
title := metadataMap["xesam:title"].String()
titleUnquoted, err := strconv.Unquote(title)
if err != nil {
titleUnquoted = "bug: strconv unquoting fail"
}
if titleUnquoted == "" {
return ""
}
output.WriteString(fmt.Sprintf(
"%s - %s",
strings.Join(artists, ", "),
titleUnquoted,
))
return html.EscapeString(output.String())
}
func get_battery_status() string {
obj := CONN.dbusSystem.Object("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/battery_"+BATTERY)
percentageProp, err := obj.GetProperty("org.freedesktop.UPower.Device.Percentage")
if err != nil {
return ""
}
percentage := fmt.Sprintf("%.0f", percentageProp.Value().(float64))
stateProp, err := obj.GetProperty("org.freedesktop.UPower.Device.State")
if err != nil {
return percentage
}
stateVal := stateProp.Value().(uint32)
state := battery_state_to_string(stateVal)
timeStr := ""
if stateVal == 1 { // charging
timeToFullProp, err := obj.GetProperty("org.freedesktop.UPower.Device.TimeToFull")
if err == nil {
timeToFull := timeToFullProp.Value().(int64)
if timeToFull > 0 {
timeStr = fmt.Sprintf(" (%s until full)", format_time_duration(timeToFull))
}
}
} else if stateVal == 2 { // discharging
timeToEmptyProp, err := obj.GetProperty("org.freedesktop.UPower.Device.TimeToEmpty")
if err == nil {
timeToEmpty := timeToEmptyProp.Value().(int64)
if timeToEmpty > 0 {
timeStr = fmt.Sprintf(" (%s remaining)", format_time_duration(timeToEmpty))
}
}
}
return fmt.Sprintf("%s%%%s%s", percentage, state, timeStr)
}
func battery_state_to_string(state uint32) string {
switch state {
case 1:
return " Charging"
case 2:
return " Discharging"
case 3:
return " Empty"
case 4:
return "" // less clutter
case 5:
return " Pending charge"
case 6:
return " Pending discharge"
default:
return " Unknown"
}
}
func format_time_duration(secs int64) string {
hours := secs / 3600
minutes := (secs % 3600) / 60
return fmt.Sprintf("%d:%02d", hours, minutes)
}
func dbus_battery_handler(feedback chan bool) {
err := CONN.dbusSystem.AddMatchSignal(
dbus.WithMatchSender("org.freedesktop.UPower"),
dbus.WithMatchObjectPath("/org/freedesktop/UPower/devices/battery_"+BATTERY),
dbus.WithMatchInterface("org.freedesktop.DBus.Properties"),
dbus.WithMatchMember("PropertiesChanged"),
)
if err != nil {
warn("Failed to add DBUS battery handler", err)
return
}
sigs := make(chan *dbus.Signal, 100)
CONN.dbusSystem.Signal(sigs)
for range sigs {
CACHE.Delete(CACHE_BATTERY)
feedback <- true
}
}