Next: Signals, Previous: Asynchronous Methods, Up: Top

## 6 Offering own methods.

Emacs can also offer 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`’.

It could be also an implementation of an 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. ‘`Application`’ is the name of the application which provides the interface.

— Constant: dbus-service-emacs

> The well known service name of Emacs.

— Constant: dbus-path-emacs

> The object path head "/org/gnu/Emacs" used by Emacs. All object paths, used by offered methods or signals, shall start with this string.

— Function: dbus-register-method bus service path interface method handler

> With this function, an application registers method on the D-Bus bus.

> bus is either the symbol `:system` or the symbol `:session`.

> service is the D-Bus service name of the D-Bus object method is registered for. It must be a known name.

> path is the D-Bus object path service is registered.

> 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 Type Conversion.

> 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.

> In case handler shall return a reply message with an empty argument list, handler must return the symbol `:ignore`.

> 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 shall 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)
>                 (let (result)
>                   (if (find-file filename)
>                       (setq result '(:boolean t))
>                     (setq result '(:boolean nil)))
>                   result))

>               ⇒ my-dbus-method-handler

>               (dbus-register-method
>                 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
>                 "org.freedesktop.TextEditor" "OpenFile"
>                 'my-dbus-method-handler)

>               ⇒ ((: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 filename as parameter, the file is opened in Emacs, and the method returns either true or false, indicating the success of the method. As 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 raising the Emacs signal `dbus-error`. The handler above could be changed like this:

>               (defun my-dbus-method-handler (&rest args)
>                 (unless (and (= (length args) 1) (stringp (car args)))
>                   (signal 'dbus-error (list (format "Wrong argument list: %S" args))))
>                 (condition-case err
>                     (find-file (car args))
>                   (error (signal 'dbus-error (cdr err))))
>                 t)

>               ⇒ my-dbus-method-handler

> The test runs then

>               # 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.DBus.Error.Failed:
>                  Wrong argument list: ("/etc/hosts" "/etc/passwd")

— Function: dbus-register-property bus service path interface property access value &optional emits-signal

> With this function, an application declares a property on the D-Bus bus.

> bus is either the symbol `:system` or the symbol `: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.

> 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 symbol `:read` or `:readwrite`. value is the initial value of the property, it can be of any valid type (see `dbus-call-method` for details).

> 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 `: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`.

> Example:

>               (dbus-register-property
>                 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
>                 "org.freedesktop.TextEditor" "name" :read "GNU Emacs")

>               ⇒ ((: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)

>               ⇒ ((: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 Properties and Annotations).

>               (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"

— Function: dbus-unregister-object object

> Unregister object from the D-Bus. object must be the result of a preceding `dbus-register-method`, `dbus-register-property` or `dbus-register-signal` call (see Signals). 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.

— Function: dbus-unregister-service bus service

> Unregister all objects from D-Bus bus, registered by Emacs for service.

> bus is either the symbol `:system` or the symbol `: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.