// NewDBusProxy creates a new dbus proxy. func NewDBusProxy(conn *dbus.Conn, dest string, objPath string, iface string, flags dbus.Flags) (*DBusProxy, error) { if conn == nil { return nil, ErrorProxyNilConnection } if dest == "" { return nil, ErrorProxyEmptyDestination } if objPath == "" { return nil, ErrorProxyEmptyObjectPath } if !dbus.ObjectPath(objPath).IsValid() { return nil, ErrorProxyInvalidObjectPath } if iface == "" { return nil, ErrorProxyEmptyInterface } obj := conn.Object(dest, dbus.ObjectPath(objPath)) proxy := &DBusProxy{ conn: conn, obj: obj, dest: dest, objPath: objPath, iface: iface, introspectorIface: "org.freedesktop.DBus.Introspectable", flags: flags, sigChanMap: map[string][]Signal{}, } runtime.SetFinalizer(proxy, func(proxy *DBusProxy) { proxy.finalize() }) return proxy, nil }
func (manager *MonitorManager) Watch(fileURI string) (string, dbus.ObjectPath, string, error) { watcherID := atomic.AddUint32(&_WatcherCounter, 1) watcher, err := NewWatcher(watcherID, fileURI) if err != nil { return "", dbus.ObjectPath("/"), "", err } if err := dbus.InstallOnSession(watcher); err != nil { watcher.finalize() return "", dbus.ObjectPath("/"), "", err } manager.watchers[WatcherID(watcherID)] = watcher dbusInfo := watcher.GetDBusInfo() return dbusInfo.Dest, dbus.ObjectPath(dbusInfo.ObjectPath), dbusInfo.Interface, nil }
func (manager *MonitorManager) Monitor(fileURI string, flags uint32) (string, dbus.ObjectPath, string, error) { monitorID := atomic.AddUint32(&_MonitorCounter, 1) monitor, err := NewMonitor(monitorID, fileURI, gio.FileMonitorFlags(flags)) if monitor == nil { return "", dbus.ObjectPath("/"), "", err } if err := dbus.InstallOnSession(monitor); err != nil { Log.Error("Install Monitor to Session Bus failed:", err) monitor.finalize() return "", dbus.ObjectPath("/"), "", err } manager.monitors[MonitorID(monitorID)] = monitor dbusInfo := monitor.GetDBusInfo() return dbusInfo.Dest, dbus.ObjectPath(dbusInfo.ObjectPath), dbusInfo.Interface, nil }
// Because empty object path is invalid, so JobObjectPath is used as default value. // So empty interface means install failed. func installJob(job dbus.DBusObject) (string, dbus.ObjectPath, string, error) { dest := "" objPath := dbus.ObjectPath(d.JobObjectPath) iface := "" if job == nil { Log.Warning("cannot install a nil object on dbus.") return dest, objPath, iface, errors.New("cannot install a nil object on dbus.") } err := dbus.InstallOnSession(job) if err != nil { Log.Warning("install dbus on session bus failed:", err) return dest, objPath, iface, err } dbusInfo := job.GetDBusInfo() return dbusInfo.Dest, dbus.ObjectPath(dbusInfo.ObjectPath), dbusInfo.Interface, nil }
// create a new operation from fn and install it to session bus. // NB: using closure and anonymous function is ok, // but variable-length argument list is much more safer and much more portable. func newOperationJob(paths []string, fn func([]string, ...interface{}) dbus.DBusObject, args ...interface{}) (string, dbus.ObjectPath, string, error) { objPath := dbus.ObjectPath(d.JobObjectPath) iface := "" srcURLs := make([]string, len(paths)) for i, path := range paths { srcURL, err := pathToURL(path) if err != nil { Log.Error("convert path to URL failed:", err) return "", objPath, iface, err // maybe continue is a better choice. } srcURLs[i] = srcURL.String() } return installJob(fn(srcURLs, args...)) }
func (proxy *DBusProxy) Subscribe(sigName string, f interface{}) func() { sig := proxy.createSignalChan(sigName) rule := proxy.buildRule(sigName) proxy.conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) go func() { fn := reflect.ValueOf(f) for v := range sig.Chan { if v.Name != SignalName(proxy.iface, sigName) || v.Path != dbus.ObjectPath(proxy.objPath) { continue } l := len(v.Body) args := make([]reflect.Value, l) for i, v := range v.Body { args[i] = reflect.ValueOf(v) } fn.Call(args) } }() return func() { proxy.removeSignalChan(sig) } }