1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
package dbusutil
import (
"sync"
"github.com/godbus/dbus"
)
type SignalHandlerId int
type SignalLoop struct {
conn *dbus.Conn
bufSize int
ch chan *dbus.Signal
mu sync.Mutex
handlers map[SignalHandlerId]SignalHandler
nextHandlerId SignalHandlerId
}
func NewSignalLoop(conn *dbus.Conn, bufSize int) *SignalLoop {
pl := &SignalLoop{
conn: conn,
bufSize: bufSize,
handlers: make(map[SignalHandlerId]SignalHandler),
nextHandlerId: 1,
}
return pl
}
func (sl *SignalLoop) Conn() *dbus.Conn {
return sl.conn
}
func (sl *SignalLoop) Start() {
ch := make(chan *dbus.Signal, sl.bufSize)
sl.conn.Signal(ch)
sl.ch = ch
go func() {
for signal := range ch {
sl.process(signal)
}
}()
}
func (sl *SignalLoop) process(signal *dbus.Signal) {
var cbs []SignalHandlerFunc
sl.mu.Lock()
for _, handler := range sl.handlers {
if handler.rule.match(signal) {
if handler.cb != nil {
cbs = append(cbs, handler.cb)
}
}
}
sl.mu.Unlock()
for _, cb := range cbs {
cb(signal)
}
}
func (sl *SignalLoop) Stop() {
sl.conn.RemoveSignal(sl.ch)
close(sl.ch)
}
func (sl *SignalLoop) AddHandler(rule *SignalRule, cb SignalHandlerFunc) SignalHandlerId {
sl.mu.Lock()
defer sl.mu.Unlock()
id := sl.nextHandlerId
sl.nextHandlerId++
sl.handlers[id] = SignalHandler{
rule: rule,
cb: cb,
}
return id
}
func (sl *SignalLoop) RemoveHandler(id SignalHandlerId) {
if id < 0 {
return
}
sl.mu.Lock()
delete(sl.handlers, id)
sl.mu.Unlock()
}
type SignalHandler struct {
rule *SignalRule
cb SignalHandlerFunc
}
type SignalRule struct {
Sender string
Path dbus.ObjectPath
Name string
}
func (m *SignalRule) match(sig *dbus.Signal) bool {
if m == nil {
return true
}
if m.Sender != "" && m.Sender != sig.Sender {
// define sender, but not equal
return false
}
if m.Path != "" && m.Path != sig.Path {
// define path, but not equal
return false
}
if m.Name != "" && m.Name != sig.Name {
// define name, but not equal
return false
}
return true
}
type SignalHandlerFunc func(sig *dbus.Signal)
|