208 lines
4.8 KiB
Go
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
|
|
}
|
|
}
|