initial commit
This commit is contained in:
146
monitor/monitor.go
Normal file
146
monitor/monitor.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
|
||||
"led-controller/config"
|
||||
)
|
||||
|
||||
type Event int
|
||||
|
||||
const (
|
||||
DisplayOn Event = iota
|
||||
DisplayOff
|
||||
)
|
||||
|
||||
type Monitor struct {
|
||||
cfg *config.Config
|
||||
events chan<- Event
|
||||
}
|
||||
|
||||
func New(cfg *config.Config, events chan<- Event) (*Monitor, error) {
|
||||
return &Monitor{cfg: cfg, events: events}, nil
|
||||
}
|
||||
|
||||
func (m *Monitor) Run(ctx context.Context) {
|
||||
method := m.cfg.Monitor.Method
|
||||
|
||||
if method == "screensaver" || method == "all" {
|
||||
go m.watchScreenSaver(ctx)
|
||||
}
|
||||
if method == "logind" || method == "all" {
|
||||
go m.watchLogind(ctx)
|
||||
}
|
||||
|
||||
<-ctx.Done()
|
||||
}
|
||||
|
||||
// watchScreenSaver listens on the session bus for org.freedesktop.ScreenSaver.ActiveChanged
|
||||
// This covers GNOME, KDE, XFCE, and other freedesktop-compliant DEs.
|
||||
func (m *Monitor) watchScreenSaver(ctx context.Context) {
|
||||
conn, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
log.Printf("screensaver monitor: cannot connect to session bus: %v", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Match both the freedesktop and GNOME screensaver interfaces
|
||||
rules := []string{
|
||||
"type='signal',interface='org.freedesktop.ScreenSaver',member='ActiveChanged'",
|
||||
"type='signal',interface='org.gnome.ScreenSaver',member='ActiveChanged'",
|
||||
}
|
||||
|
||||
for _, rule := range rules {
|
||||
call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule)
|
||||
if call.Err != nil {
|
||||
log.Printf("screensaver monitor: AddMatch failed for %q: %v", rule, call.Err)
|
||||
}
|
||||
}
|
||||
|
||||
sigCh := make(chan *dbus.Signal, 16)
|
||||
conn.Signal(sigCh)
|
||||
|
||||
log.Println("screensaver monitor: listening for ActiveChanged signals")
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case sig := <-sigCh:
|
||||
if sig == nil {
|
||||
return
|
||||
}
|
||||
if sig.Name == "org.freedesktop.ScreenSaver.ActiveChanged" ||
|
||||
sig.Name == "org.gnome.ScreenSaver.ActiveChanged" {
|
||||
if len(sig.Body) < 1 {
|
||||
continue
|
||||
}
|
||||
active, ok := sig.Body[0].(bool)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if active {
|
||||
log.Println("screensaver monitor: screen locked/blanked")
|
||||
m.events <- DisplayOff
|
||||
} else {
|
||||
log.Println("screensaver monitor: screen unlocked/unblanked")
|
||||
m.events <- DisplayOn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// watchLogind listens on the system bus for org.freedesktop.login1.Manager.PrepareForSleep.
|
||||
// This catches system suspend/resume events.
|
||||
func (m *Monitor) watchLogind(ctx context.Context) {
|
||||
conn, err := dbus.ConnectSystemBus()
|
||||
if err != nil {
|
||||
log.Printf("logind monitor: cannot connect to system bus: %v", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
rule := "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'"
|
||||
call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule)
|
||||
if call.Err != nil {
|
||||
log.Printf("logind monitor: AddMatch failed: %v", call.Err)
|
||||
return
|
||||
}
|
||||
|
||||
sigCh := make(chan *dbus.Signal, 16)
|
||||
conn.Signal(sigCh)
|
||||
|
||||
log.Println("logind monitor: listening for PrepareForSleep signals")
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case sig := <-sigCh:
|
||||
if sig == nil {
|
||||
return
|
||||
}
|
||||
if sig.Name == "org.freedesktop.login1.Manager.PrepareForSleep" {
|
||||
if len(sig.Body) < 1 {
|
||||
continue
|
||||
}
|
||||
preparing, ok := sig.Body[0].(bool)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if preparing {
|
||||
log.Println("logind monitor: system preparing to sleep")
|
||||
m.events <- DisplayOff
|
||||
} else {
|
||||
log.Println("logind monitor: system woke up")
|
||||
m.events <- DisplayOn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user