From f3aaedc9839b922517179212a6aca2d646a43139 Mon Sep 17 00:00:00 2001 From: Kimiblock Moe Date: Wed, 25 Mar 2026 17:31:54 +0800 Subject: [PATCH] Use dconf monitor to keep an eye on show-banner --- gnome-dnd.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 8 ++++-- snotify.go | 80 +--------------------------------------------------- 3 files changed, 78 insertions(+), 82 deletions(-) create mode 100644 gnome-dnd.go diff --git a/gnome-dnd.go b/gnome-dnd.go new file mode 100644 index 0000000..931f39e --- /dev/null +++ b/gnome-dnd.go @@ -0,0 +1,72 @@ +package main + +import ( + "log" + "os/exec" + "strconv" + "strings" + "syscall" + + "github.com/godbus/dbus/v5" +) + +func monitorGNOMEDND() { + go updateDnd() + type sigChange struct { + prefix string + changes []string + tag string + } + conn, err := dbus.ConnectSessionBus() + if err != nil { + panic(err) + } + obj := conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus") + call := obj.Call( + "org.freedesktop.DBus.AddMatch", + 0, + "type='signal',path='/ca/desrt/dconf/Writer/user',interface='ca.desrt.dconf.Writer',member='Notify'", + ) + log.Println("Monitoring DnD") + if call.Err != nil { + log.Fatalln("Could not monitor DND status:", call.Err) + } + sigChan := make(chan *dbus.Signal, 10) + conn.Signal(sigChan) + + for sig := range sigChan { + var chg sigChange + if sig.Name == "ca.desrt.dconf.Writer.Notify" && + sig.Path == "/ca/desrt/dconf/Writer/user" { + err := dbus.Store(sig.Body, &chg.prefix, &chg.changes, &chg.tag) + if err != nil { + log.Fatalln("Could not store change:", err) + } + if chg.prefix == "/org/gnome/desktop/notifications/show-banners" { + go updateDnd() + } + } + } +} + +func updateDnd() { + cmdline := []string{"get", "org.gnome.desktop.notifications", "show-banners"} + cmd := exec.Command("gsettings", cmdline...) + attr := &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } + cmd.SysProcAttr = attr + out, err := cmd.Output() + if err != nil { + log.Fatalln("Could not get banner state:", err) + } + output := strings.TrimSuffix(string(out), "\n") + boolVal, err := strconv.ParseBool(output) + if err != nil { + log.Fatalln("Could not get banner state:", err) + } + dndLock.Lock() + soundAllowed = boolVal + dndLock.Unlock() + log.Println("Updated show-banner status:", boolVal) +} \ No newline at end of file diff --git a/go.mod b/go.mod index fc65c8a..fa5e02e 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,13 @@ module snotify go 1.26.1 -require github.com/godbus/dbus/v5 v5.2.2 +require ( + github.com/godbus/dbus/v5 v5.2.2 + github.com/jfreymuth/oggvorbis v1.0.5 + github.com/jfreymuth/pulse v0.1.1 +) require ( - github.com/jfreymuth/oggvorbis v1.0.5 // indirect - github.com/jfreymuth/pulse v0.1.1 // indirect github.com/jfreymuth/vorbis v1.0.2 // indirect golang.org/x/sys v0.27.0 // indirect ) diff --git a/snotify.go b/snotify.go index 562b1ea..24581f8 100644 --- a/snotify.go +++ b/snotify.go @@ -1,16 +1,10 @@ package main import ( - "bufio" "errors" - "fmt" "log" "os" - "os/exec" - "strconv" - "strings" "sync" - "syscall" "github.com/godbus/dbus/v5" "github.com/jfreymuth/oggvorbis" @@ -57,79 +51,7 @@ func dndWatcher() () { env := os.Getenv("XDG_CURRENT_DESKTOP") switch env { case "GNOME": - valCmdSlice := []string{ - "stdbuf", - "-oL", - "gsettings", - "monitor", - "org.gnome.desktop.notifications", - "show-banners", - } - getCmdSlice := []string{ - "gsettings", - "get", - "org.gnome.desktop.notifications", - "show-banners", - } - cmd := exec.Command(valCmdSlice[0], valCmdSlice[1:]...) - attr := syscall.SysProcAttr{ - Pdeathsig: syscall.SIGTERM, - } - cmd.SysProcAttr = &attr - var wg sync.WaitGroup - wg.Add(1) - go func () { - pipe, err := cmd.StdoutPipe() - wg.Wait() - if err != nil { - log.Println("GSettings failed:", err) - return - } - scanner := bufio.NewScanner(pipe) - cmdGet, err := exec.Command(getCmdSlice[0], getCmdSlice[1:]...).Output() - if err != nil { - log.Println("GSettings failed:", err) - return - } - line := string(cmdGet) - rawVal := strings.TrimSpace(line) - log.Println("Allow sound:", rawVal) - val, err := strconv.ParseBool(rawVal) - if err != nil { - log.Println("Could not parse result:", err) - - } else { - dndLock.Lock() - soundAllowed = val - dndLock.Unlock() - } - for scanner.Scan() { - line := scanner.Text() - log.Println("Allow status changed:", line) - rawVal := strings.TrimPrefix(line, "show-banners:") - rawVal = strings.TrimSpace(rawVal) - val, err := strconv.ParseBool(rawVal) - if err != nil { - log.Println("Could not parse result:", err) - continue - } - dndLock.Lock() - soundAllowed = val - dndLock.Unlock() - } - } () - wg.Done() - err := cmd.Start() - if err != nil { - fmt.Println("Could not start DnD monitor:", err) - return - } - log.Println("Started DnD watcher") - err = cmd.Wait() - if err != nil { - fmt.Println("GSettings monitor returned error:", err) - return - } + monitorGNOMEDND() default: log.Println("Do not disturb unsupported:", env) }