split into multiple files
This commit is contained in:
parent
a4077a3d8b
commit
86dc6b8f54
9 changed files with 309 additions and 280 deletions
23
cache.go
Normal file
23
cache.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// cache key definitions
|
||||||
|
CACHE_BT_CONNECTED = "bt_connected"
|
||||||
|
CACHE_BT_BATTERY = "bt_battery"
|
||||||
|
CACHE_MEDIA = "media"
|
||||||
|
CACHE_LAYOUT = "kbd_layout"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CACHE = sync.Map{}
|
||||||
|
|
||||||
|
func getC[T comparable](c sync.Map, id string, fallback func() T) T {
|
||||||
|
val, ok := c.Load(id)
|
||||||
|
if !ok {
|
||||||
|
val = fallback()
|
||||||
|
c.Store(id, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.(T)
|
||||||
|
}
|
54
connections.go
Normal file
54
connections.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
sway "github.com/joshuarubin/go-sway"
|
||||||
|
"github.com/noisetorch/pulseaudio"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CONN Connections
|
||||||
|
|
||||||
|
type Connections struct {
|
||||||
|
dbusSession, dbusSystem *dbus.Conn
|
||||||
|
paClient *pulseaudio.Client
|
||||||
|
swayClient sway.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func init_connections() (Connections, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
dbusSession, err := dbus.ConnectSessionBus()
|
||||||
|
if err != nil {
|
||||||
|
return Connections{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dbusSystem, err := dbus.ConnectSystemBus()
|
||||||
|
if err != nil {
|
||||||
|
return Connections{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
paClient, err := pulseaudio.NewClient()
|
||||||
|
if err != nil {
|
||||||
|
return Connections{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
swayClient, err := sway.New(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return Connections{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Connections{
|
||||||
|
dbusSession: dbusSession,
|
||||||
|
dbusSystem: dbusSystem,
|
||||||
|
paClient: paClient,
|
||||||
|
swayClient: swayClient,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Connections) close_all() {
|
||||||
|
c.dbusSession.Close()
|
||||||
|
c.dbusSystem.Close()
|
||||||
|
c.paClient.Close()
|
||||||
|
}
|
7
consts.go
Normal file
7
consts.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
SEPARATOR = " | "
|
||||||
|
BATTERY = "BAT0"
|
||||||
|
HEADSET = "94:DB:56:6B:E3:8A"
|
||||||
|
)
|
6
go.mod
6
go.mod
|
@ -4,10 +4,12 @@ go 1.19
|
||||||
|
|
||||||
require github.com/godbus/dbus/v5 v5.1.0
|
require github.com/godbus/dbus/v5 v5.1.0
|
||||||
|
|
||||||
require github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861
|
require (
|
||||||
|
github.com/joshuarubin/go-sway v1.2.0
|
||||||
|
github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/joshuarubin/go-sway v1.2.0 // indirect
|
|
||||||
github.com/joshuarubin/lifecycle v1.0.0 // indirect
|
github.com/joshuarubin/lifecycle v1.0.0 // indirect
|
||||||
go.uber.org/atomic v1.3.2 // indirect
|
go.uber.org/atomic v1.3.2 // indirect
|
||||||
go.uber.org/multierr v1.1.0 // indirect
|
go.uber.org/multierr v1.1.0 // indirect
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -1,3 +1,4 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
@ -7,8 +8,10 @@ github.com/joshuarubin/lifecycle v1.0.0 h1:N/lPEC8f+dBZ1Tn99vShqp36LwB+LI7XNAiNa
|
||||||
github.com/joshuarubin/lifecycle v1.0.0/go.mod h1:sRy++ATvR9Ee21tkRdFkQeywAWvDsue66V70K0Dnl54=
|
github.com/joshuarubin/lifecycle v1.0.0/go.mod h1:sRy++ATvR9Ee21tkRdFkQeywAWvDsue66V70K0Dnl54=
|
||||||
github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861 h1:Xng5X+MlNK7Y/Ede75B86wJgaFMFvuey1K4Suh9k2E4=
|
github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861 h1:Xng5X+MlNK7Y/Ede75B86wJgaFMFvuey1K4Suh9k2E4=
|
||||||
github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861/go.mod h1:/zosM8PSkhuVyfJ9c/qzBhPSm3k06m9U4y4SDfH0jeA=
|
github.com/noisetorch/pulseaudio v0.0.0-20220603053345-9303200c3861/go.mod h1:/zosM8PSkhuVyfJ9c/qzBhPSm3k06m9U4y4SDfH0jeA=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
|
113
module_dbus.go
Normal file
113
module_dbus.go
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"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, 1)
|
||||||
|
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, 1)
|
||||||
|
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, 1)
|
||||||
|
metadataMap["xesam:artist"].Store(&artists)
|
||||||
|
title := metadataMap["xesam:title"].String()
|
||||||
|
|
||||||
|
if title == "\"\"" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
output.WriteString(fmt.Sprintf(
|
||||||
|
"%s - %s",
|
||||||
|
strings.Join(artists, ", "),
|
||||||
|
title[1:len(title)-1],
|
||||||
|
))
|
||||||
|
|
||||||
|
return output.String()
|
||||||
|
}
|
42
module_pulseaudio.go
Normal file
42
module_pulseaudio.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
func pulseaudio_handler(feedback chan bool) {
|
||||||
|
vol, muted := get_default_sink_volume()
|
||||||
|
|
||||||
|
sigs, err := CONN.paClient.Updates()
|
||||||
|
if err != nil {
|
||||||
|
warn("Failed to create PulseAudio update listener!", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for range sigs {
|
||||||
|
nVol, nMuted := get_default_sink_volume()
|
||||||
|
if nVol != vol || nMuted != muted {
|
||||||
|
feedback <- true
|
||||||
|
vol = nVol
|
||||||
|
muted = nMuted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_default_sink_volume() (int, bool) {
|
||||||
|
si, err := CONN.paClient.ServerInfo()
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
sinks, err := CONN.paClient.Sinks()
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range sinks {
|
||||||
|
if sinks[i].Name == si.DefaultSink {
|
||||||
|
return int(math.Round(float64(sinks[i].Cvolume[0]) / float64(sinks[i].BaseVolume) * 100)), sinks[i].Muted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
63
module_sway.go
Normal file
63
module_sway.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
sway "github.com/joshuarubin/go-sway"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sway_handler struct {
|
||||||
|
sway.EventHandler
|
||||||
|
feedback chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h sway_handler) Input(ctx context.Context, ev sway.InputEvent) {
|
||||||
|
if ev.Change != "xkb_layout" || ev.Input.Type != "keyboard" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
oldval, _ := CACHE.Load(CACHE_LAYOUT)
|
||||||
|
if oldval == *ev.Input.XKBActiveLayoutName {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHE.Store(CACHE_LAYOUT, *ev.Input.XKBActiveLayoutName)
|
||||||
|
h.feedback <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func sway_input_handler(feedback chan bool) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var h sway.EventHandler = sway_handler{feedback: feedback}
|
||||||
|
|
||||||
|
sway.Subscribe(ctx, h, sway.EventTypeInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_current_layout() string {
|
||||||
|
ctx := context.Background()
|
||||||
|
inputs, err := CONN.swayClient.GetInputs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
warn("Failed to get Sway inputs!", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, input := range inputs {
|
||||||
|
if input.Type != "keyboard" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return *input.XKBActiveLayoutName
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func long_layout_to_short(layout string) string {
|
||||||
|
switch layout {
|
||||||
|
case "English (US)":
|
||||||
|
return "US"
|
||||||
|
case "Estonian":
|
||||||
|
return "ET"
|
||||||
|
}
|
||||||
|
|
||||||
|
return layout
|
||||||
|
}
|
278
statusbar.go
278
statusbar.go
|
@ -1,94 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
sway "github.com/joshuarubin/go-sway"
|
|
||||||
|
|
||||||
"github.com/godbus/dbus/v5"
|
|
||||||
"github.com/noisetorch/pulseaudio"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
SEPARATOR = " | "
|
|
||||||
BATTERY = "BAT0"
|
|
||||||
HEADSET = "94:DB:56:6B:E3:8A"
|
|
||||||
|
|
||||||
// cache key definitions
|
|
||||||
CACHE_BT_CONNECTED = "bt_connected"
|
|
||||||
CACHE_BT_BATTERY = "bt_battery"
|
|
||||||
CACHE_MEDIA = "media"
|
|
||||||
CACHE_LAYOUT = "kbd_layout"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
CONN Connections
|
|
||||||
CACHE = sync.Map{}
|
|
||||||
HEADSET_PATH = dbus.ObjectPath("/org/bluez/hci0/dev_" + strings.ReplaceAll(HEADSET, ":", "_"))
|
|
||||||
)
|
|
||||||
|
|
||||||
func getC[T comparable](c sync.Map, id string, fallback func() T) T {
|
|
||||||
val, ok := c.Load(id)
|
|
||||||
if !ok {
|
|
||||||
val = fallback()
|
|
||||||
c.Store(id, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
return val.(T)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Connections struct {
|
|
||||||
dbusSession, dbusSystem *dbus.Conn
|
|
||||||
paClient *pulseaudio.Client
|
|
||||||
swayClient sway.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func init_connections() (Connections, error) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
dbusSession, err := dbus.ConnectSessionBus()
|
|
||||||
if err != nil {
|
|
||||||
return Connections{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dbusSystem, err := dbus.ConnectSystemBus()
|
|
||||||
if err != nil {
|
|
||||||
return Connections{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
paClient, err := pulseaudio.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return Connections{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
swayClient, err := sway.New(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return Connections{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return Connections{
|
|
||||||
dbusSession: dbusSession,
|
|
||||||
dbusSystem: dbusSystem,
|
|
||||||
paClient: paClient,
|
|
||||||
swayClient: swayClient,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Connections) close_all() {
|
|
||||||
c.dbusSession.Close()
|
|
||||||
c.dbusSystem.Close()
|
|
||||||
c.paClient.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
update := make(chan bool, 1)
|
update := make(chan bool, 1)
|
||||||
var err error // so assigning the global works
|
var err error // so assigning the global works
|
||||||
|
@ -185,66 +105,6 @@ func produce_output() string {
|
||||||
return output.String()
|
return output.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 1)
|
|
||||||
metadataMap["xesam:artist"].Store(&artists)
|
|
||||||
title := metadataMap["xesam:title"].String()
|
|
||||||
|
|
||||||
if title == "\"\"" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
output.WriteString(fmt.Sprintf(
|
|
||||||
"%s - %s",
|
|
||||||
strings.Join(artists, ", "),
|
|
||||||
title[1:len(title)-1],
|
|
||||||
))
|
|
||||||
|
|
||||||
return output.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func signal_handler(feedback chan bool) {
|
func signal_handler(feedback chan bool) {
|
||||||
// SIGUSR1 can be sent to manually trigger a reprint
|
// SIGUSR1 can be sent to manually trigger a reprint
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
|
@ -269,141 +129,3 @@ func time_handler(feedback chan bool) {
|
||||||
feedback <- true
|
feedback <- true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 1)
|
|
||||||
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, 1)
|
|
||||||
CONN.dbusSession.Signal(sigs)
|
|
||||||
|
|
||||||
for range sigs {
|
|
||||||
CACHE.Delete(CACHE_MEDIA)
|
|
||||||
feedback <- true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func get_default_sink_volume() (int, bool) {
|
|
||||||
si, err := CONN.paClient.ServerInfo()
|
|
||||||
if err != nil {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
sinks, err := CONN.paClient.Sinks()
|
|
||||||
if err != nil {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range sinks {
|
|
||||||
if sinks[i].Name == si.DefaultSink {
|
|
||||||
return int(math.Round(float64(sinks[i].Cvolume[0]) / float64(sinks[i].BaseVolume) * 100)), sinks[i].Muted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func pulseaudio_handler(feedback chan bool) {
|
|
||||||
vol, muted := get_default_sink_volume()
|
|
||||||
|
|
||||||
sigs, err := CONN.paClient.Updates()
|
|
||||||
if err != nil {
|
|
||||||
warn("Failed to create PulseAudio update listener!", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for range sigs {
|
|
||||||
nVol, nMuted := get_default_sink_volume()
|
|
||||||
if nVol != vol || nMuted != muted {
|
|
||||||
feedback <- true
|
|
||||||
vol = nVol
|
|
||||||
muted = nMuted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func get_current_layout() string {
|
|
||||||
ctx := context.Background()
|
|
||||||
inputs, err := CONN.swayClient.GetInputs(ctx)
|
|
||||||
if err != nil {
|
|
||||||
warn("Failed to get Sway inputs!", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, input := range inputs {
|
|
||||||
if input.Type != "keyboard" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return *input.XKBActiveLayoutName
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func long_layout_to_short(layout string) string {
|
|
||||||
switch layout {
|
|
||||||
case "English (US)":
|
|
||||||
return "US"
|
|
||||||
case "Estonian":
|
|
||||||
return "ET"
|
|
||||||
}
|
|
||||||
|
|
||||||
return layout
|
|
||||||
}
|
|
||||||
|
|
||||||
type sway_handler struct {
|
|
||||||
sway.EventHandler
|
|
||||||
feedback chan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h sway_handler) Input(ctx context.Context, ev sway.InputEvent) {
|
|
||||||
if ev.Change != "xkb_layout" || ev.Input.Type != "keyboard" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
oldval, _ := CACHE.Load(CACHE_LAYOUT)
|
|
||||||
if oldval == *ev.Input.XKBActiveLayoutName {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
CACHE.Store(CACHE_LAYOUT, *ev.Input.XKBActiveLayoutName)
|
|
||||||
h.feedback <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
func sway_input_handler(feedback chan bool) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
var h sway.EventHandler = sway_handler{feedback: feedback}
|
|
||||||
|
|
||||||
sway.Subscribe(ctx, h, sway.EventTypeInput)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue