// onSubBuildMenu fills the menu with stream actions: select device. // func (app *Applet) onSubBuildMenu(icon string, menu cdtype.Menuer) { // stream actions menu: select device. dev := app.pulse.Stream(dbus.ObjectPath(icon)) mute, _ := dev.Bool("Mute") menu.AddCheckEntry("Mute volume", mute, func() { toggleMute(dev) }) sel, es := dev.ObjectPath("Device") if log.Err(es) { return } app.menuAddDevices(menu, sel, "Output", func(sink dbus.ObjectPath) error { return dev.Call("Move", 0, sink).Err }) // Kill works but seem to leave the client app into a bugged state (same for stream or client kill). // app.menu.Append("Kill", func() { // // log.Err(dev.Call("Kill", 0).Err, "Kill") // kill stream. // client, ec := dev.ObjectPath("Client") // if ec != nil { // return // } // app.pulse.Client.Client(client).Call("Kill", 0) // kill client. // }) }
func (c *Conn) initDispatch() { ch := make(chan *dbus.Signal, signalBuffer) c.sysconn.Signal(ch) go func() { for { signal, ok := <-ch if !ok { return } switch signal.Name { case "org.freedesktop.systemd1.Manager.JobRemoved": c.jobComplete(signal) unitName := signal.Body[2].(string) var unitPath dbus.ObjectPath c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath) if unitPath != dbus.ObjectPath("") { c.sendSubStateUpdate(unitPath) } case "org.freedesktop.systemd1.Manager.UnitNew": c.sendSubStateUpdate(signal.Body[1].(dbus.ObjectPath)) case "org.freedesktop.DBus.Properties.PropertiesChanged": if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" { // we only care about SubState updates, which are a Unit property c.sendSubStateUpdate(signal.Path) } } } }() }
func (app *Applet) onSubMiddleClick(icon string) { switch app.conf.MiddleAction { case 3: // TODO: need more actions and constants to define them. log.Debug("mute") toggleMute(app.pulse.Stream(dbus.ObjectPath(icon))) } }
func recurseObjects(bus *dbus.Conn, service, prefix string) ([]string, error) { var s string err := bus.Object(service, dbus.ObjectPath(prefix)).Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&s) if err != nil { return nil, err } var n introspect.Node err = xml.Unmarshal([]byte(s), &n) if err != nil { return nil, err } names := make([]string, 0, 100) if len(n.Interfaces) > 1 { names = append(names, prefix) } for _, child := range n.Children { childPath := path.Join(prefix, child.Name) items, err := recurseObjects(bus, service, childPath) if err != nil { return nil, err } names = append(names, items...) } return names, nil }
func (a *AllJoynBridge) fetchAboutData(svcInfo *AllJoynServiceInfo, objInfo *AllJoynBindingInfo) error { obj := a.bus.Object(svcInfo.dbusService, dbus.ObjectPath(objInfo.dbusPath)) call := obj.Call(AJ_ABOUT_GETABOUTDATA, 0, "en") if call.Err != nil { log.Printf("Error calling %s: %v", AJ_ABOUT_GETABOUTDATA, call.Err) return call.Err } // fill aboutData with values call.Store(&aboutData) log.Printf("ABOUT: %+v", aboutData) for key, value := range aboutData { // log.Printf("%s(%s)", key, value.Signature()) switch value.Signature().String() { case "ay": C.SetProperty(C.CString(key), unsafe.Pointer(C.CString(fmt.Sprintf("%x", value.Value())))) default: C.SetProperty(C.CString(key), unsafe.Pointer(C.CString(value.String()))) } } return nil }
func newDbusServer() (*dbusServer, error) { conn, err := dbus.SystemBus() if err != nil { return nil, err } reply, err := conn.RequestName(busName, dbus.NameFlagDoNotQueue) if err != nil { return nil, err } if reply != dbus.RequestNameReplyPrimaryOwner { return nil, errors.New("Bus name is already owned") } ds := &dbusServer{} if err := conn.Export(ds, objectPath, interfaceName); err != nil { return nil, err } ps := strings.Split(objectPath, "/") path := "/" for _, p := range ps { if len(path) > 1 { path += "/" } path += p if err := conn.Export(ds, dbus.ObjectPath(path), "org.freedesktop.DBus.Introspectable"); err != nil { return nil, err } } ds.conn = conn ds.prompter = newPrompter(conn) return ds, nil }
// ObjectPath creates a dbus.ObjectPath using the rules that systemd uses for // serializing special characters. func ObjectPath(path string) dbus.ObjectPath { path = strings.Replace(path, ".", "_2e", -1) path = strings.Replace(path, "-", "_2d", -1) path = strings.Replace(path, "@", "_40", -1) return dbus.ObjectPath(path) }
func (c *Conn) initConnection() error { var err error c.sysconn, err = dbus.SystemBusPrivate() if err != nil { return err } // Only use EXTERNAL method, and hardcode the uid (not username) // to avoid a username lookup (which requires a dynamically linked // libc) methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} err = c.sysconn.Auth(methods) if err != nil { c.sysconn.Close() return err } err = c.sysconn.Hello() if err != nil { c.sysconn.Close() return err } c.sysobj = c.sysconn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1")) // Setup the listeners on jobs so that we can get completions c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, "type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'") c.initSubscription() c.initDispatch() return nil }
func traverseDbusObjects(bus *dbus.Conn, dbusService, dbusPath string, fn func(path string, node *introspect.Node)) { var xmldata string var node introspect.Node var o = bus.Object(dbusService, dbus.ObjectPath(dbusPath)) err := o.Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&xmldata) if err != nil { log.Printf("Error getting introspect from [%s, %s]: %s", dbusService, dbusPath, err) } err = xml.NewDecoder(strings.NewReader(xmldata)).Decode(&node) if err != nil { log.Printf("Error decoding introspect from [%s, %s]: %s", dbusService, dbusPath, err) } // log.Printf("Introspect: %+v", node) if node.Name != "" && len(node.Interfaces) > 0 { fn(dbusPath, &node) } for _, child := range node.Children { traverseDbusObjects(bus, dbusService, dbusPath+"/"+child.Name, fn) } }
// GetClient return a connection to the active instance of the internal Dbus // service if any. Return nil, nil if none found. // InterfacePath is an optional string to provide if the object use an interface // path different from SrvObj // func GetClient(SrvObj, SrvPath string, InterfacePath ...string) (*Client, error) { conn, ec := dbus.SessionBus() if ec != nil { return nil, ec } reply, e := conn.RequestName(SrvObj, dbus.NameFlagDoNotQueue) if e != nil { return nil, e } conn.ReleaseName(SrvObj) if reply == dbus.RequestNameReplyPrimaryOwner { // no active instance. return nil, errors.New("no service found") } if len(InterfacePath) == 0 { // Set default interface path = object name. InterfacePath = []string{SrvObj} } // Found active instance, return client. return &Client{ BusObject: conn.Object(SrvObj, dbus.ObjectPath(SrvPath)), srvObj: InterfacePath[0], testErr: func(e error, method string) {}, }, nil }
func newDbus() (*logindDbus, error) { conn, err := dbus.SystemBusPrivate() if err != nil { return nil, err } methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} err = conn.Auth(methods) if err != nil { conn.Close() return nil, err } err = conn.Hello() if err != nil { conn.Close() return nil, err } object := conn.Object(dbusObject, dbus.ObjectPath(dbusPath)) return &logindDbus{ conn: conn, object: object, }, nil }
func (c *Conn) initConnection() error { var err error c.sysconn, err = dbus.SystemBusPrivate() if err != nil { return err } err = c.sysconn.Auth(nil) if err != nil { c.sysconn.Close() return err } err = c.sysconn.Hello() if err != nil { c.sysconn.Close() return err } c.sysobj = c.sysconn.Object("org.freedesktop.systemd1", dbus.ObjectPath("/org/freedesktop/systemd1")) // Setup the listeners on jobs so that we can get completions c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, "type='signal', interface='org.freedesktop.systemd1.Manager', member='JobRemoved'") c.initSubscription() c.initDispatch() return nil }
func main() { bus, err := dbus.SystemBus() bus.RequestName("com.devicehive.alljoyn.test.basic", dbus.NameFlagDoNotQueue) if err != nil { log.Panic(err) } basicService := NewBasicService(bus) bus.Export(basicService, "/com/devicehive/alljoyn/test/basic", "org.alljoyn.About") bus.Export(basicService, "/com/devicehive/alljoyn/test/basic", "org.alljoyn.Bus.sample") bus.Export(basicService, "/com/devicehive/alljoyn/test/basic", "org.freedesktop.DBus.Introspectable") // Now try to register ourself in AllJoyn via dbus go func() { bridge := bus.Object("com.devicehive.alljoyn.bridge", dbus.ObjectPath("/com/devicehive/alljoyn/bridge")) res := bridge.Call("com.devicehive.alljoyn.bridge.AddService", 0, "/com/devicehive/alljoyn/test/basic", "com.devicehive.alljoyn.test.basic", "/sample", "org.alljoyn.Bus.sample", "") log.Printf("Result: %+v", res) res = bridge.Call("com.devicehive.alljoyn.bridge.StartAllJoyn", 0, "com.devicehive.alljoyn.test.basic") }() select {} }
func (c *Conn) initConnection() error { var err error c.conn, err = dbus.SystemBusPrivate() if err != nil { return err } // Only use EXTERNAL method, and hardcode the uid (not username) // to avoid a username lookup (which requires a dynamically linked // libc) methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} err = c.conn.Auth(methods) if err != nil { c.conn.Close() return err } err = c.conn.Hello() if err != nil { c.conn.Close() return err } c.object = c.conn.Object("org.freedesktop.login1", dbus.ObjectPath(dbusPath)) return nil }
func (m *AllJoynMessenger) callRemoteMethod(message *C.AJ_Message, path, member string, arguments []interface{}) (err error) { log.Printf("MSG: message.hdr=%p", message.hdr) remote := m.bus.Object(m.dbusService, dbus.ObjectPath(path)) // log.Printf("%s Argument[0] %+v", member, reflect.ValueOf(arguments[0]).Type()) res := remote.Call(member, 0, arguments...) if res.Err != nil { log.Printf("Error calling dbus method (%s): %s", member, res.Err) return res.Err } //pad := 4 - (int)(message.bodyBytes)%4 //C.WriteBytes((*C.AJ_Message)(message), nil, (C.size_t)(0), (C.size_t)(pad)) buf := new(bytes.Buffer) buf.Write(make([]byte, (int)(message.bodyBytes))) enc := ajmarshal.NewEncoderAtOffset(buf, (int)(message.bodyBytes), binary.LittleEndian) pad, err := enc.Encode(res.Body...) // log.Printf("Padding of the encoded buffer: %d", pad) if err != nil { log.Printf("Error encoding result: %s", err) return err } /* C.AJ_MarshalContainer((*C.AJ_Message)(message), (*C.AJ_Arg)(C.Get_Arg()), C.AJ_ARG_ARRAY) C.AJ_MarshalArgs_cgo((*C.AJ_Message)(message), C.CString("{sv}"), C.CString("DeviceName"), C.CString("s"), C.CString("Golang-device")) C.AJ_MarshalCloseContainer((*C.AJ_Message)(message), (*C.AJ_Arg)(C.Get_Arg())) */ //log.Printf("Encoded reply, len: %+v, %d", buf.Bytes(), buf.Len()) // log.Printf("Length before: %d", message.bodyBytes) newBuf := buf.Bytes()[(int)(message.bodyBytes)+pad:] //log.Printf("Buffer to write into AllJoyn: %+v, %d", newBuf, len(newBuf)) // hdr := message.hdr // if hdr.flags&C.uint8_t(C.AJ_FLAG_ENCRYPTED) == 0 { // hdr = nil // } else { // message.hdr.flags &= ^C.uint8_t(C.AJ_FLAG_ENCRYPTED) // } if len(newBuf) > 0 { log.Printf("MSG: message.hdr=%p", message.hdr) C.AJ_DeliverMsgPartial((*C.AJ_Message)(message), C.uint32_t(len(newBuf))) log.Printf("MSG: message.hdr=%p", message.hdr) C.AJ_MarshalRaw((*C.AJ_Message)(message), unsafe.Pointer(&newBuf[0]), C.size_t(len(newBuf))) } else { C.AJ_MarshalRaw((*C.AJ_Message)(message), unsafe.Pointer(&newBuf), C.size_t(0)) } //log.Printf("New buff reply, len: %+v, %d", newBuf, len(newBuf)) // if hdr != nil { // message.hdr = hdr // message.hdr.flags &= ^C.uint8_t(C.AJ_FLAG_ENCRYPTED) // } log.Printf("MSG: message.hdr=%p", message.hdr) return nil }
func (d *dbusWrapper) call(name string, args ...interface{}) *dbus.Call { c := d.conn.Object(d.iface, dbus.ObjectPath(d.path)).Call(d.iface+"."+name, 0, args...) if c.Err != nil { log.Printf("Error calling %s: %s", name, c.Err) } return c }
func (c *testLogindInterface) getSession(session logindSessionEntry) *logindSession { sessions := map[dbus.ObjectPath]*logindSession{ dbus.ObjectPath("/org/freedesktop/login1/session/1"): { seat: session.SeatId, remote: "true", sessionType: knownStringOrOther("tty", attrTypeValues), class: knownStringOrOther("user", attrClassValues), }, dbus.ObjectPath("/org/freedesktop/login1/session/2"): { seat: session.SeatId, remote: "false", sessionType: knownStringOrOther("x11", attrTypeValues), class: knownStringOrOther("greeter", attrClassValues), }, } return sessions[session.SessionObjectPath] }
func (c *testLogindInterface) listSessions() ([]logindSessionEntry, error) { return []logindSessionEntry{ { SessionId: "1", UserId: 0, UserName: "", SeatId: "", SessionObjectPath: dbus.ObjectPath("/org/freedesktop/login1/session/1"), }, { SessionId: "2", UserId: 0, UserName: "", SeatId: "seat0", SessionObjectPath: dbus.ObjectPath("/org/freedesktop/login1/session/2"), }, }, nil }
// EmitSignal emits a signal on conn func (conn *DBusFakeConnection) EmitSignal(name, path, iface, signal string, args ...interface{}) { sig := &godbus.Signal{ Sender: name, Path: godbus.ObjectPath(path), Name: iface + "." + signal, Body: args, } for _, ch := range conn.signalHandlers { ch <- sig } }
func (app *Applet) onSubScroll(icon string, up bool) { dev := app.pulse.Stream(dbus.ObjectPath(icon)) values, e := dev.ListUint32("Volume") if log.Err(e) { return } delta := app.conf.VolumeStep if !up { delta = -delta } log.Err(dev.Set("Volume", VolumeDelta(values, delta))) }
func ConnectToDBus(bus string) (*DBusClient, error) { c := new(DBusClient) var err error switch bus { case "session": c.bus, err = dbus.SessionBus() case "system": c.bus, err = dbus.SystemBus() default: c.bus, err = dbus.Dial(bus) } if err != nil { return nil, err } if !c.bus.SupportsUnixFDs() { return nil, errors.New("DBus connection does not support file descriptors") } c.path = dbus.ObjectPath("/com/firelizzard/teasvc/Client") err = c.bus.Export(c, c.path, "com.firelizzard.teasvc.Client") if err != nil { return nil, err } c.sigchans = make(map[string](chan *dbus.Signal)) chsig := make(chan *dbus.Signal, 10) go func() { for { sig := <-chsig ch, ok := c.sigchans[sig.Name] if !ok { log.Print("Unhandled signal: " + sig.Name) } select { case ch <- sig: // sent singal, done default: log.Print("Unhandled signal (full channel): " + sig.Name) } } }() c.bus.Signal(chsig) c.bus.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, "type='signal',interface='com.firelizzard.teasvc',member='Pong'") return c, nil }
func New() *Interface { bus, err := dbus.SystemBus() if err != nil { return &Interface{} } fw := &Interface{ obj: bus.Object(firewalldName, dbus.ObjectPath(firewalldPath)), } go fw.dbusSignalHandler(bus) return fw }
// Start starts the DBus service with the given object. // Introspection will be managed and the provided properties exposed. // Methods will also be auto discovered. // func (load *Server) Start(obj interface{}, propsSpec map[string]map[string]*prop.Prop) (bool, error) { reply, e := load.Conn.RequestName(load.srvObj, dbus.NameFlagDoNotQueue) if e != nil { return false, e } if reply != dbus.RequestNameReplyPrimaryOwner { return false, nil } // Everything OK, we can register our Dbus methods. e = load.Conn.Export(obj, dbus.ObjectPath(load.srvPath), load.srvObj) if load.Log.Err(e, "register service object") { return false, e } introNode := load.Introspect(obj, propsSpec) e = load.Conn.Export(introspect.NewIntrospectable(introNode), dbus.ObjectPath(load.srvPath), "org.freedesktop.DBus.Introspectable") if load.Log.Err(e, "register service introspect") { return false, e } return true, nil }
// DisplayStreamVolume renders the given stream volume on the subicon. // func (ap *AppPulse) DisplayStreamVolume(name string, values []uint32) error { mute, e := ap.Stream(dbus.ObjectPath(name)).Bool("Mute") if e != nil { return e // no mute, check if need to send values?? } label := VolumeToPercent(VolumeToFloat(values)) emblem := "" if mute { // label += " [M]" emblem = ap.icon.FileLocation("img", DefaultIconMuted) } ap.icon.SubIcon(name).SetEmblem(emblem, EmblemMuted) return ap.icon.SubIcon(name).SetQuickInfo(label) }
// Introspect provides introspection data for the DBus service to start. // // propsSpec example: // // var propsSpec = map[string]map[string]*prop.Prop{ // SrvObj: { // "Restart": { // int32(0), // true, // prop.EmitTrue, // func(c *prop.Change) *dbus.Error { // fmt.Println(c.Name, "changed to", c.Value) // return nil // }, // }, // }, // } // func (load *Server) Introspect(obj interface{}, propsSpec map[string]map[string]*prop.Prop) *introspect.Node { var props []introspect.Property if propsSpec != nil { tmp := prop.New(load.Conn, dbus.ObjectPath(load.srvPath), propsSpec) props = tmp.Introspection(load.srvObj) } return &introspect.Node{ Name: load.srvPath, Interfaces: []introspect.Interface{ prop.IntrospectData, { Name: load.srvObj, Methods: introspect.Methods(obj), Properties: props, }, }, } }
func (c *Conn) dispatch() { ch := make(chan *dbus.Signal, signalBuffer) c.sigconn.Signal(ch) go func() { for { signal, ok := <-ch if !ok { return } if signal.Name == "org.freedesktop.systemd1.Manager.JobRemoved" { c.jobComplete(signal) } if c.subscriber.updateCh == nil { continue } var unitPath dbus.ObjectPath switch signal.Name { case "org.freedesktop.systemd1.Manager.JobRemoved": unitName := signal.Body[2].(string) c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath) case "org.freedesktop.systemd1.Manager.UnitNew": unitPath = signal.Body[1].(dbus.ObjectPath) case "org.freedesktop.DBus.Properties.PropertiesChanged": if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" { unitPath = signal.Path } } if unitPath == dbus.ObjectPath("") { continue } c.sendSubStateUpdate(unitPath) } }() }
// New creates a new applet instance with args from command line. // func New(callnew cdtype.NewAppletFunc, args []string, dir string) (cdtype.AppInstance, *CDDbus, func() error) { name := args[0][2:] // Strip ./ in the beginning. base := cdapplet.New() base.SetBase(name, args[3], args[4], dir) app := cdapplet.Start(callnew, base) if app == nil { return nil, nil, nil } // app.ParentAppName = args[5] backend := &CDDbus{ icons: make(map[string]*SubIcon), busPath: dbus.ObjectPath(args[2]), menu: &Menu{}, log: app.Log(), } app.SetBackend(backend) callinit := app.SetEvents(app) return app, backend, callinit }
func ExportToDBus(proc *Process, bus string) (*DBusServer, error) { s := new(DBusServer) s.proc = proc var err error switch bus { case "session": s.bus, err = dbus.SessionBus() case "system": s.bus, err = dbus.SystemBus() default: s.bus, err = dbus.Dial(bus) } if err != nil { return nil, err } if !s.bus.SupportsUnixFDs() { return nil, errors.New("DBus connection does not support file descriptors") } s.path = dbus.ObjectPath("/com/firelizzard/teasvc/Server") go s.handleSignals() err = s.bus.Export(s, s.path, "com.firelizzard.teasvc.Server") if err != nil { return nil, err } c := s.bus.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, "type='signal',interface='com.firelizzard.teasvc',member='Ping'") if c.Err != nil { return nil, c.Err } return s, nil }
func New() (c *Client, err error) { c = new(Client) c.conn, err = dbus.SystemBusPrivate() if err != nil { c.conn.Close() return nil, err } methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))} err = c.conn.Auth(methods) if err != nil { c.conn.Close() return nil, err } err = c.conn.Hello() if err != nil { c.conn.Close() return nil, err } c.object = c.conn.Object(dbusInterface, dbus.ObjectPath(dbusPath)) // Setup the filter for the StatusUpdate signals match := fmt.Sprintf("type='signal',interface='%s',member='%s'", dbusInterface, dbusMember) call := c.conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, match) if call.Err != nil { return nil, err } c.ch = make(chan *dbus.Signal, signalBuffer) c.conn.Signal(c.ch) return c, nil }
func handleListInterfaces(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bus := getBus(vars) if bus == nil { http.NotFound(w, r) return } var s string err := bus.Object(vars["service"], dbus.ObjectPath(r.URL.Query().Get("objectPath"))).Call("org.freedesktop.DBus.Introspectable.Introspect", 0).Store(&s) if err != nil { http.Error(w, err.Error(), 500) return } var n introspect.Node err = xml.Unmarshal([]byte(s), &n) if err != nil { http.Error(w, err.Error(), 500) return } js(w, &n) }