diff --git a/default_handler.go b/default_handler.go index cfe8fb2..ed88f29 100644 --- a/default_handler.go +++ b/default_handler.go @@ -117,11 +117,24 @@ type exportedMethod struct { reflect.Value } -func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) { +func (m exportedMethod) Call(sender Sender, args ...interface{}) ([]interface{}, error) { t := m.Type() - params := make([]reflect.Value, len(args)) - for i := 0; i < len(args); i++ { + hasSenderParam := false + if m.NumArguments() > 0 && m.Type().In(0) == reflect.TypeOf(sender) { + hasSenderParam = true + } + + params := make([]reflect.Value, m.NumArguments()) + + startIdxForArgumentsCopy := 0 + if hasSenderParam { + params[0] = reflect.ValueOf(sender) + startIdxForArgumentsCopy = 1 + } + + for i := startIdxForArgumentsCopy; i < m.NumArguments(); i++ { + reflect.TypeOf(&ErrMsgInvalidArg) params[i] = reflect.ValueOf(args[i]).Elem() } diff --git a/export.go b/export.go index d3dd9f7..2b26354 100644 --- a/export.go +++ b/export.go @@ -59,6 +59,9 @@ func MakeFailedError(err error) *Error { // sender. type Sender string +// Destination is a type which can be used to specify a receiver for signals. +type Destination string + func computeMethodName(name string, mapping map[string]string) string { newname, ok := mapping[name] if ok { @@ -190,7 +193,7 @@ func (conn *Conn) handleCall(msg *Message) { return } - ret, err := m.Call(args...) + ret, err := m.Call(Sender(sender), args...) if err != nil { conn.sendError(err, sender, serial) return @@ -218,6 +221,23 @@ func (conn *Conn) handleCall(msg *Message) { } } +func (conn *Conn) EmitWithDestination(path ObjectPath, name string, dest Destination, values ...interface{}) error { + i := strings.LastIndex(name, ".") + if i == -1 { + return errors.New("dbus: invalid method name") + } + iface := name[:i] + member := name[i+1:] + + headers := make(map[HeaderField]Variant) + headers[FieldInterface] = MakeVariant(iface) + headers[FieldMember] = MakeVariant(member) + headers[FieldPath] = MakeVariant(path) + headers[FieldDestination] = MakeVariant(string(dest)) + + return conn.emitWithHeaders(headers, values...) +} + // Emit emits the given signal on the message bus. The name parameter must be // formatted as "interface.member", e.g., "org.freedesktop.DBus.NameLost". func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) error { @@ -227,12 +247,21 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro } iface := name[:i] member := name[i+1:] + + headers := make(map[HeaderField]Variant) + headers[FieldInterface] = MakeVariant(iface) + headers[FieldMember] = MakeVariant(member) + headers[FieldPath] = MakeVariant(path) + + return conn.emitWithHeaders(headers, values...) +} + +func (conn *Conn) emitWithHeaders(headers map[HeaderField]Variant, values ...interface{}) error { + msg := new(Message) msg.Type = TypeSignal - msg.Headers = make(map[HeaderField]Variant) - msg.Headers[FieldInterface] = MakeVariant(iface) - msg.Headers[FieldMember] = MakeVariant(member) - msg.Headers[FieldPath] = MakeVariant(path) + msg.Headers = headers + msg.Body = values if len(values) > 0 { msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...)) diff --git a/server_interfaces.go b/server_interfaces.go index e4e0389..68431f8 100644 --- a/server_interfaces.go +++ b/server_interfaces.go @@ -38,7 +38,7 @@ type Interface interface { // A Method represents the exposed methods on D-Bus. type Method interface { // Call requires that all arguments are decoded before being passed to it. - Call(args ...interface{}) ([]interface{}, error) + Call(sender Sender, args ...interface{}) ([]interface{}, error) NumArguments() int NumReturns() int // ArgumentValue returns a representative value for the argument at position diff --git a/server_interfaces_test.go b/server_interfaces_test.go index 96044a5..2b9bfa6 100644 --- a/server_interfaces_test.go +++ b/server_interfaces_test.go @@ -109,7 +109,7 @@ func (t *tester) LookupMethod(name string) (Method, bool) { } // Method -func (t *tester) Call(args ...interface{}) ([]interface{}, error) { +func (t *tester) Call(sender Sender, args ...interface{}) ([]interface{}, error) { return args, nil } @@ -131,7 +131,7 @@ func (t *tester) ReturnValue(position int) interface{} { type terrfn func(in string) error -func (t terrfn) Call(args ...interface{}) ([]interface{}, error) { +func (t terrfn) Call(sender Sender, args ...interface{}) ([]interface{}, error) { return nil, t(*args[0].(*string)) } @@ -194,7 +194,7 @@ func (t *tester) RetireSerial(serial uint32) {} type intro_fn func() string -func (intro intro_fn) Call(args ...interface{}) ([]interface{}, error) { +func (intro intro_fn) Call(sender Sender, args ...interface{}) ([]interface{}, error) { return []interface{}{intro()}, nil }