Next: Sending and receiving signals., Previous: Calling methods non-blocking., Up: D-Bus integration in Emacs [Contents][Index]
You can offer an own service in D-Bus, which will be visible by other D-Bus clients. See https://dbus.freedesktop.org/doc/dbus-api-design.html for a discussion of the design.
In order to register methods on the D-Bus, Emacs has to request a well known name on the D-Bus under which it will be available for other clients. Names on the D-Bus can be registered and unregistered using the following functions:
This function registers the known name service on D-Bus bus.
bus is either the keyword :system
or the keyword
:session
.
service is the service name to be registered on the D-Bus. It must be a known name.
flags is a subset of the following keywords:
:allow-replacement
Allow another service to become the primary owner if requested.
:replace-existing
Request to replace the current primary owner.
:do-not-queue
If we can not become the primary owner do not place us in the queue.
One of the following keywords is returned:
:primary-owner
We have become the primary owner of the name service.
:in-queue
We could not become the primary owner and have been placed in the queue.
:exists
We already are in the queue.
:already-owner
We already are the primary owner.
This function unregisters all objects from D-Bus bus, that were registered by Emacs for service.
bus is either the keyword :system
or the keyword
:session
.
service is the D-Bus service name of the D-Bus. It must be a known name. Emacs releases its association to service from D-Bus.
One of the following keywords is returned:
:released
We successfully released the name service.
:non-existent
The name service does not exist on the bus.
:not-owner
We are not an owner of the name service.
When service is not a known name but a unique name, the function returns nil.
When a name has been chosen, Emacs can offer its own methods, which can be called by other applications. These methods could be an implementation of an interface of a well known service, like ‘org.freedesktop.TextEditor’.
They could also be an implementation of its own interface. In this
case, the service name must be ‘org.gnu.Emacs’. The object path
shall begin with ‘/org/gnu/Emacs/application’, and the
interface name shall be org.gnu.Emacs.application
, where
application is the name of the application which provides the
interface.
The well known service name ‘org.gnu.Emacs’ of Emacs.
The object path namespace ‘/org/gnu/Emacs’ used by Emacs.
The interface namespace org.gnu.Emacs
used by Emacs.
With this function, an application registers method on the D-Bus bus.
bus is either the keyword :system
or the keyword
:session
.
service is the D-Bus service name of the D-Bus object method is registered for. It must be a known name (see discussion of dont-register-service below).
path is the D-Bus object path service is registered (see discussion of dont-register-service below).
interface is the interface offered by service. It must provide method.
handler is a Lisp function to be called when a method call is received. It must accept as arguments the input arguments of method. handler should return a list, whose elements are to be used as arguments for the reply message of method. This list can be composed like the input parameters in Mapping Lisp types and D-Bus types..
If handler wants to return just one Lisp object and it is not a cons cell, handler can return this object directly, instead of returning a list containing the object.
If handler returns a reply message with an empty argument list,
handler must return the keyword :ignore
in order to
distinguish it from nil
(the boolean false).
If handler detects an error, it shall return the list
(:error error-name error-message)
.
error-name is a namespaced string which characterizes the error
type, and error-message is a free text string. Alternatively,
any Emacs signal dbus-error
in handler raises a D-Bus
error message with the error name ‘org.freedesktop.DBus.Error.Failed’.
When dont-register-service is non-nil
, the known name
service is not registered. This means that other D-Bus clients
have no way of noticing the newly registered method. When interfaces
are constructed incrementally by adding single methods or properties
at a time, dont-register-service can be used to prevent other
clients from discovering the still incomplete interface.
The default D-Bus timeout when waiting for a message reply is 25 seconds. This value could be even smaller, depending on the calling client. Therefore, handler should not last longer than absolutely necessary.
dbus-register-method
returns a Lisp object, which can be used
as argument in dbus-unregister-object
for removing the
registration for method. Example:
(defun my-dbus-method-handler (filename) (if (find-file filename) '(:boolean t) '(:boolean nil))) (dbus-register-method :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" "org.freedesktop.TextEditor" "OpenFile" #'my-dbus-method-handler) ⇒ ((:method :session "org.freedesktop.TextEditor" "OpenFile") ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" my-dbus-method-handler))
If you invoke the method ‘org.freedesktop.TextEditor.OpenFile’
from another D-Bus application with a file name as parameter, the file
is opened in Emacs, and the method returns either true or
false, indicating the success of the method. As a test tool one
could use the command line tool dbus-send
in a shell:
# dbus-send --session --print-reply \ --dest="org.freedesktop.TextEditor" \ "/org/freedesktop/TextEditor" \ "org.freedesktop.TextEditor.OpenFile" string:"/etc/hosts" -| method return sender=:1.22 -> dest=:1.23 reply_serial=2 boolean true
You can indicate an error by returning an :error
list reply, or
by raising the Emacs signal dbus-error
. The handler above
could be changed like this:
(defun my-dbus-method-handler (&rest args) (if (not (and (= (length args) 1) (stringp (car args)))) (list :error "org.freedesktop.TextEditor.Error.InvalidArgs" (format "Wrong argument list: %S" args)) (condition-case err (find-file (car args)) (error (signal 'dbus-error (cdr err)))) t))
The test then runs
# dbus-send --session --print-reply \ --dest="org.freedesktop.TextEditor" \ "/org/freedesktop/TextEditor" \ "org.freedesktop.TextEditor.OpenFile" \ string:"/etc/hosts" string:"/etc/passwd" -| Error org.freedesktop.TextEditor.Error.InvalidArgs: Wrong argument list: ("/etc/hosts" "/etc/passwd")
# dbus-send --session --print-reply \ --dest="org.freedesktop.TextEditor" \ "/org/freedesktop/TextEditor" \ "org.freedesktop.TextEditor.OpenFile" \ string:"/etc/crypttab" -| Error org.freedesktop.DBus.Error.Failed: D-Bus error: "File is not readable", "/etc/crypttab"
With this function, an application declares a property on the D-Bus bus.
bus is either the keyword :system
or the keyword
:session
.
service is the D-Bus service name of the D-Bus. It must be a known name.
path is the D-Bus object path service is registered (see discussion of dont-register-service below).
interface is the name of the interface used at path, property is the name of the property of interface.
access indicates, whether the property can be changed by other
services via D-Bus. It must be either the keyword :read
,
:write
or :readwrite
.
value is the initial value of the property, it can be of any valid type (See dbus-call-method, for details). value can be preceded by a type keyword.
If property already exists on path, it will be
overwritten. For properties with access type :read
this is the
only way to change their values. Properties with access type
:write
or :readwrite
can be changed by
dbus-set-property
.
The interface ‘org.freedesktop.DBus.Properties’ is added to
path, including a default handler for the ‘Get’,
‘GetAll’ and ‘Set’ methods of this interface. When
emits-signal is non-nil
, the signal
‘PropertiesChanged’ is sent when the property is changed by
dbus-set-property
.
When dont-register-service is non-nil
, the known name
service is not registered. This means that other D-Bus clients
have no way of noticing the newly registered method. When interfaces
are constructed incrementally by adding single methods or properties
at a time, dont-register-service can be used to prevent other
clients from discovering the still incomplete interface.
dbus-register-property
returns a Lisp object, which can be used
as argument in dbus-unregister-object
for removing the
registration for property. Example:
(dbus-register-property :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" "org.freedesktop.TextEditor" "name" :read "GNU Emacs") ⇒ ((:property :session "org.freedesktop.TextEditor" "name") ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor")) (dbus-register-property :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" "org.freedesktop.TextEditor" "version" :readwrite emacs-version t) ⇒ ((:property :session "org.freedesktop.TextEditor" "version") ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"))
Other D-Bus applications can read the property via the default methods
‘org.freedesktop.DBus.Properties.Get’ and
‘org.freedesktop.DBus.Properties.GetAll’. Testing is also
possible via the command line tool dbus-send
in a shell:
# dbus-send --session --print-reply \ --dest="org.freedesktop.TextEditor" \ "/org/freedesktop/TextEditor" \ "org.freedesktop.DBus.Properties.GetAll" \ string:"org.freedesktop.TextEditor" -| method return sender=:1.22 -> dest=:1.23 reply_serial=3 array [ dict entry( string "name" variant string "GNU Emacs" ) dict entry( string "version" variant string "23.1.50.5" ) ]
It is also possible to apply the dbus-get-property
,
dbus-get-all-properties
and dbus-set-property
functions
(see What else to know about interfaces.).
(dbus-set-property :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" "org.freedesktop.TextEditor" "version" "23.1.50") ⇒ "23.1.50" (dbus-get-property :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" "org.freedesktop.TextEditor" "version") ⇒ "23.1.50"
This function unregisters object from the D-Bus. object
must be the result of a preceding dbus-register-method
,
dbus-register-property
, dbus-register-signal
(see Sending and receiving signals.) or dbus-register-monitor
call. It returns
t
if object has been unregistered, nil
otherwise.
When object identifies the last method or property, which is registered for the respective service, Emacs releases its association to the service from D-Bus.
Next: Sending and receiving signals., Previous: Calling methods non-blocking., Up: D-Bus integration in Emacs [Contents][Index]