Reputation: 33
I am trying to make a notification server with godbus but i cant properly export my server object to dbus and dbus only recognizes my introspect xml. I am following https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html to implement it. I have also used _example/server.go in godbus repo as you might notice in my server code provided below. Here is the server code:
package main
import (
"fmt"
"os"
"github.com/godbus/dbus/v5"
"github.com/godbus/dbus/v5/introspect"
)
const xml = `
<node>
<interface name="org.freedesktop.Notifications">
<method name="Notify">
<arg direction="in" type="s"/>
<arg direction="in" type="u"/>
<arg direction="in" type="s"/>
<arg direction="in" type="s"/>
<arg direction="in" type="s"/>
<arg direction="in" type="as"/>
<arg direction="in" type="a{sv}"/>
<arg direction="in" type="i"/>
<arg direction="out" type="u"/>
</method>
<method name="GetCapabilities">
<arg direction="out" type="as"/>
</method>
<method name="GetServerInformation">
<arg direction="out" type="s"/>
<arg direction="out" type="s"/>
<arg direction="out" type="s"/>
<arg direction="out" type="s"/>
</method>
<method name="CloseNotification">
<arg direction="in" type="u"/>
</method>
<signal name="NotificationClosed">
<arg type="u" name="id"/>
<arg type="u" name="reason"/>
</signal>
</interface>` + introspect.IntrospectDataString + `</node> `
type NotificationServer struct {
}
func (s *NotificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
fmt.Printf("New notification: %s\n", body)
return 0, nil
}
func (s *NotificationServer) GetCapabilities() ([]string, *dbus.Error) {
return []string{"action-icons", "actions", "body", "body-hyperlinks", "body-images", "body-markup", "icon-multi", "icon-static", "persistence", "sound"}, nil
}
func (s *NotificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
return "antarctica", "antarctica.com", "1.0", "1.2", nil
}
func (s *NotificationServer) CloseNotification(id uint32) *dbus.Error {
s.NotificationClosed(id, 0)
return nil
}
func (s *NotificationServer) NotificationClosed(id, reason uint32) {
}
func main() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
panic(err)
}
defer conn.Close()
reply, err := conn.RequestName("com.antarctica.notification",
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
server := NotificationServer{}
err = conn.Export(server,"/org/freedesktop/Notifications","org.freedesktop.Notifications")
if err != nil {
panic(err)
}
conn.Export(introspect.Introspectable(xml), "/org/freedesktop/Notifications", "org.freedesktop.DBus.Introspectable")
fmt.Println("Listening on com.antarctica.notification / /com/antarctica/notification ...")
select {}
}
Now the problem is that eventho the introspect xml is accessible to client:
$ gdbus introspect --session --dest com.antarctica.notification --object-path /org/freedesktop/Notifications --xml
> returns xml
I cant use org.freedesktop.Notifications methods that i wrote in my server code. for example Notify is Unknown/Invalid and this is the same for each method:
$ dbus-send --session --print-reply=literal --dest=com.antarctica.notification /org/freedesktop/Notifications org.freedesktop.Notifications.Notify
> Error org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method 'Notify'
Also in qdbusviewer when I try to execute any method it says "Unable to find method x on path /org/freedesktop/Notifications in interface org.freedesktop.Notifications"
What I have tried:
Upvotes: 3
Views: 1290
Reputation: 136
This works. You made two mistakes:
You have to request 'org.freedesktop.Notifications' as name and you can not use a pointer in the func.
package main
import (
"fmt"
"os"
"github.com/godbus/dbus/v5"
)
type notificationServer struct{}
func (s notificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
fmt.Printf("New notification: %s\n", body)
return 0, nil
}
func (s notificationServer) GetCapabilities() ([]string, *dbus.Error) {
return []string{"action-icons", "actions", "body", "body-hyperlinks", "body-images", "body-markup", "icon-multi", "icon-static", "persistence", "sound"}, nil
}
func (s notificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
return "antarctica", "antarctica.com", "1.0", "1.2", nil
}
func main() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
panic(err)
}
defer conn.Close()
f := notificationServer{}
conn.Export(f, "/org/freedesktop/Notifications", "org.freedesktop.Notifications")
reply, err := conn.RequestName("org.freedesktop.Notifications", dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, "name already taken")
os.Exit(1)
}
fmt.Println("Listening...")
select {}
}
Upvotes: 2