dbus: Receiving Method Calls

 
 6 Offering own methods.
 ***********************
 
 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:
 
  -- Function: dbus-register-service bus service &rest flags
      Register the known name SERVICE on D-Bus BUS.
 
      BUS is either the symbol ‘:system’ or the symbol ‘: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.
 
  -- 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.
 
      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 a name has been chosen, Emacs can 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 ‘org.gnu.Emacs’ of Emacs.
 
  -- Constant: dbus-path-emacs
      The object path namespace ‘/org/gnu/Emacs’ used by Emacs.
 
  -- Constant: dbus-interface-emacs
      The interface namespace ‘org.gnu.Emacs’ used by Emacs.
 
  -- Function: dbus-register-method bus service path interface method
           handler dont-register-service
      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 (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 SeeType 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’.
 
      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 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)
 
           ⇒ ((: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 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 dont-register-service
      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 (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 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’.
 
      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.
 
      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
      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 (SeeSignals).  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.