emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r107995: Move functions from C to Lis


From: Michael Albinus
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r107995: Move functions from C to Lisp. Make non-blocking method calls
Date: Sun, 22 Apr 2012 16:11:43 +0200
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 107995
committer: Michael Albinus <address@hidden>
branch nick: trunk
timestamp: Sun 2012-04-22 16:11:43 +0200
message:
  Move functions from C to Lisp.  Make non-blocking method calls
  the default.  Implement further D-Bus standard interfaces.
  
  * configure.in (dbus_validate_bus_name, dbus_validate_path)
  (dbus_validate_interface, dbus_validate_member): Check also for
  these library functions
  
  * dbusbind.c (DBUS_NUM_MESSAGE_TYPES): Declare.
  (QCdbus_request_name_allow_replacement)
  (QCdbus_request_name_replace_existing)
  (QCdbus_request_name_do_not_queue)
  (QCdbus_request_name_reply_primary_owner)
  (QCdbus_request_name_reply_in_queue)
  (QCdbus_request_name_reply_exists)
  (QCdbus_request_name_reply_already_owner): Move to dbus.el.
  (QCdbus_registered_serial, QCdbus_registered_method)
  (QCdbus_registered_signal): New Lisp objects.
  (XD_DEBUG_MESSAGE): Use sizeof.
  (XD_MESSAGE_TYPE_TO_STRING, XD_OBJECT_TO_STRING)
  (XD_DBUS_VALIDATE_BUS_ADDRESS, XD_DBUS_VALIDATE_OBJECT)
  (XD_DBUS_VALIDATE_BUS_NAME, XD_DBUS_VALIDATE_PATH)
  (XD_DBUS_VALIDATE_INTERFACE, XD_DBUS_VALIDATE_MEMBER): New macros.
  (XD_CHECK_DBUS_SERIAL): Rename from CHECK_DBUS_SERIAL_GET_SERIAL.
  (xd_signature, xd_append_arg): Allow float for integer types.
  (xd_get_connection_references): New function.
  (xd_get_connection_address): Rename from xd_initialize.  Return
  cached address.
  (xd_remove_watch): Do not unset $DBUS_SESSION_BUS_ADDRESS.
  (xd_close_bus): Rename from Fdbus_close_bus.  Not needed on Lisp
  level.
  (Fdbus_init_bus): New optional arg PRIVATE.  Cache address.
  Return number of recounts.
  (Fdbus_get_unique_name): Make stronger parameter check.
  (Fdbus_message_internal): New defun.
  (Fdbus_call_method, Fdbus_call_method_asynchronously)
  (Fdbus_method_return_internal, Fdbus_method_error_internal)
  (Fdbus_send_signal, Fdbus_register_service)
  (Fdbus_register_signal, Fdbus_register_method): Move to dbus.el.
  (xd_read_message_1): Obey new structure of Vdbus_registered_objects.
  (xd_read_queued_messages): Obey new structure of Vdbus_registered_buses.
  (Vdbus_compiled_version, Vdbus_runtime_version)
  (Vdbus_message_type_invalid, Vdbus_message_type_method_call)
  (Vdbus_message_type_method_return, Vdbus_message_type_error)
  (Vdbus_message_type_signal): New defvars.
  (Vdbus_registered_buses, Vdbus_registered_objects_table): Adapt
  docstring.
  
  * net/dbus.el (dbus-message-internal): Declare function.  Remove
  unneeded function declarations.
  (defvar dbus-message-type-invalid, dbus-message-type-method-call)
  (dbus-message-type-method-return, dbus-message-type-error)
  (dbus-message-type-signal): Declare variables.  Remove local
  definitions.
  (dbus-interface-dbus, dbus-interface-peer)
  (dbus-interface-introspectable, dbus-interface-properties)
  (dbus-path-emacs, dbus-interface-emacs, dbus-return-values-table):
  Adapt docstring.
  (dbus-interface-objectmanager): New defconst.
  (dbus-call-method, dbus-call-method-asynchronously)
  (dbus-send-signal, dbus-method-return-internal)
  (dbus-method-error-internal, dbus-register-service)
  (dbus-register-signal, dbus-register-method): New defuns, moved
  from dbusbind.c
  (dbus-call-method-handler, dbus-setenv)
  (dbus-get-all-managed-objects, dbus-managed-objects-handler): New
  defuns.
  (dbus-call-method-non-blocking): Make it an obsolete function.
  (dbus-unregister-object, dbus-unregister-service)
  (dbus-handle-event, dbus-register-property)
  (dbus-property-handler): Obey the new structure of
  `bus-registered-objects'.
  (dbus-introspect): Use `dbus-call-method'.  Use a timeout.
  (dbus-get-property, dbus-set-property, dbus-get-all-properties):
  Use `dbus-call-method'.
  
  * dbus.texi (Version): New node.
  (Properties and Annotations): Mention the object manager
  interface.  Describe dbus-get-all-managed-objects.
  (Type Conversion): Floating point numbers are allowed, if an
  anteger does not fit Emacs's integer range.
  (Synchronous Methods): Remove obsolete dbus-call-method-non-blocking.
  (Asynchronous Methods): Fix description of
  dbus-call-method-asynchronously.
  (Receiving Method Calls): Fix some minor errors.  Add
  dbus-interface-emacs.
  (Signals): Describe unicast signals and the new match rules.
  (Alternative Buses): Add the PRIVATE optional argument to
  dbus-init-bus.  Describe its new return value.  Add dbus-setenv.
modified:
  ChangeLog
  configure.in
  doc/misc/ChangeLog
  doc/misc/dbus.texi
  etc/NEWS
  lisp/ChangeLog
  lisp/net/dbus.el
  src/ChangeLog
  src/dbusbind.c
=== modified file 'ChangeLog'
--- a/ChangeLog 2012-04-22 06:56:42 +0000
+++ b/ChangeLog 2012-04-22 14:11:43 +0000
@@ -1,3 +1,9 @@
+2012-04-22  Michael Albinus  <address@hidden>
+
+       * configure.in (dbus_validate_bus_name, dbus_validate_path)
+       (dbus_validate_interface, dbus_validate_member): Check also for
+       these library functions
+
 2012-04-22  Paul Eggert  <address@hidden>
 
        * configure.in (doug_lea_malloc): Check for __malloc_initialize_hook.

=== modified file 'configure.in'
--- a/configure.in      2012-04-22 06:56:42 +0000
+++ b/configure.in      2012-04-22 14:11:43 +0000
@@ -2079,8 +2079,7 @@
 fi
 
 dnl D-Bus has been tested under GNU/Linux only.  Must be adapted for
-dnl other platforms.  Support for higher D-Bus versions than 1.0 is
-dnl also not configured.
+dnl other platforms.
 HAVE_DBUS=no
 DBUS_OBJ=
 if test "${with_dbus}" = "yes"; then
@@ -2088,7 +2087,13 @@
    if test "$HAVE_DBUS" = yes; then
      LIBS="$LIBS $DBUS_LIBS"
      AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if using D-Bus.])
-     AC_CHECK_FUNCS([dbus_watch_get_unix_fd])
+     dnl dbus_watch_get_unix_fd has been introduced in D-Bus 1.1.1.
+     dnl dbus_validate_* have been introduced in D-Bus 1.5.12.
+     AC_CHECK_FUNCS(dbus_watch_get_unix_fd \
+                   dbus_validate_bus_name \
+                    dbus_validate_path \
+                   dbus_validate_interface \
+                   dbus_validate_member)
      DBUS_OBJ=dbusbind.o
    fi
 fi

=== modified file 'doc/misc/ChangeLog'
--- a/doc/misc/ChangeLog        2012-04-20 16:27:52 +0000
+++ b/doc/misc/ChangeLog        2012-04-22 14:11:43 +0000
@@ -1,3 +1,19 @@
+2012-04-22  Michael Albinus  <address@hidden>
+
+       * dbus.texi (Version): New node.
+       (Properties and Annotations): Mention the object manager
+       interface.  Describe dbus-get-all-managed-objects.
+       (Type Conversion): Floating point numbers are allowed, if an
+       anteger does not fit Emacs's integer range.
+       (Synchronous Methods): Remove obsolete dbus-call-method-non-blocking.
+       (Asynchronous Methods): Fix description of
+       dbus-call-method-asynchronously.
+       (Receiving Method Calls): Fix some minor errors.  Add
+       dbus-interface-emacs.
+       (Signals): Describe unicast signals and the new match rules.
+       (Alternative Buses): Add the PRIVATE optional argument to
+       dbus-init-bus.  Describe its new return value.  Add dbus-setenv.
+
 2012-04-20  Glenn Morris  <address@hidden>
 
        * faq.texi (New in Emacs 24): New section.

=== modified file 'doc/misc/dbus.texi'
--- a/doc/misc/dbus.texi        2012-03-02 09:40:05 +0000
+++ b/doc/misc/dbus.texi        2012-04-22 14:11:43 +0000
@@ -53,7 +53,7 @@
 * Asynchronous Methods::        Calling methods non-blocking.
 * Receiving Method Calls::      Offering own methods.
 * Signals::                     Sending and receiving signals.
-* Alternative Buses::           Alternative buses.
+* Alternative Buses::           Alternative buses and environments.
 * Errors and Events::           Errors and events.
 * Index::                       Index including concepts, functions, variables.
 
@@ -116,6 +116,7 @@
 @cindex inspection
 
 @menu
+* Version::                     Determining the D-Bus version.
 * Bus names::                   Discovering D-Bus names.
 * Introspection::               Knowing the details of D-Bus services.
 * Nodes and Interfaces::        Detecting object paths and interfaces.
@@ -125,6 +126,25 @@
 @end menu
 
 
address@hidden Version
address@hidden D-Bus version.
+
+D-Bus has evolved over the years.  New features have been added with
+new D-Bus versions.  There are two variables, which allow to determine
+the used D-Bus version.
+
address@hidden dbus-compiled-version
+This variable, a string, determines the version of D-Bus Emacs is
+compiled against.  If it cannot be determined the value is @code{nil}.
address@hidden defvar
+
address@hidden dbus-runtime-version
+The other D-Bus version to be checked is the version of D-Bus Emacs
+runs with.  This string can be different from @code{dbus-compiled-version}.
+It is also @code{nil}, if it cannot be determined at runtime.
address@hidden defvar
+
+
 @node Bus names
 @section Bus names.
 
@@ -149,7 +169,6 @@
 (member "org.gnome.evince.Daemon"
         (dbus-list-activatable-names :session))
 @end lisp
-
 @end defun
 
 @defun dbus-list-names bus
@@ -637,6 +656,12 @@
 That is, properties can be retrieved and changed during lifetime of an
 element.
 
+A generalized interface is
address@hidden@footnote{See
address@hidden://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager}},
+which returns objects, their interfaces and properties for a given
+service in just one call.
+
 Annotations, on the other hand, are static values for an element.
 Often, they are used to instruct generators, how to generate code from
 the interface for a given language binding.
@@ -732,6 +757,61 @@
 @end lisp
 @end defun
 
address@hidden dbus-get-all-managed-objects bus service path
+This functions returns all objects at @var{bus}, @var{service},
address@hidden, and the children of @var{path}.  The result is a list of
+objects.  Every object is a cons of an existing path name, and the
+list of available interface objects.  An interface object is another
+cons, which car is the interface name, and the cdr is the list of
+properties as returned by @code{dbus-get-all-properties} for that path
+and interface. Example:
+
address@hidden
+(dbus-get-all-managed-objects
+  :session "org.gnome.SettingsDaemon" "/")
+
address@hidden (("/org/gnome/SettingsDaemon/MediaKeys"
+     ("org.gnome.SettingsDaemon.MediaKeys")
+     ("org.freedesktop.DBus.Peer")
+     ("org.freedesktop.DBus.Introspectable")
+     ("org.freedesktop.DBus.Properties")
+     ("org.freedesktop.DBus.ObjectManager"))
+    ("/org/gnome/SettingsDaemon/Power"
+     ("org.gnome.SettingsDaemon.Power.Keyboard")
+     ("org.gnome.SettingsDaemon.Power.Screen")
+     ("org.gnome.SettingsDaemon.Power"
+      ("Icon" . ". GThemedIcon battery-full-charged-symbolic ")
+      ("Tooltip" . "Laptop battery is charged"))
+     ("org.freedesktop.DBus.Peer")
+     ("org.freedesktop.DBus.Introspectable")
+     ("org.freedesktop.DBus.Properties")
+     ("org.freedesktop.DBus.ObjectManager"))
+    @dots{})
address@hidden lisp
+
+If possible, @samp{org.freedesktop.DBus.ObjectManager.GetManagedObjects}
+is used for retrieving the information.  Otherwise, the information
+is collected via @samp{org.freedesktop.DBus.Introspectable.Introspect}
+and @samp{org.freedesktop.DBus.Properties.GetAll}, which is slow.
+
+An overview of all existing object paths, their interfaces and
+properties could be retrieved by the following code:
+
address@hidden
+(with-current-buffer (switch-to-buffer "*objectmanager*")
+  (erase-buffer)
+  (let (result)
+    (dolist (service (dbus-list-known-names :session) result)
+      (message "%s" service)
+      (add-to-list
+       'result
+       (cons service
+             (dbus-get-all-managed-objects :session service "/"))))
+    (insert (message "%s" (pp result)))
+    (redisplay t)))
address@hidden lisp
address@hidden defun
+
 @defun dbus-introspect-get-annotation-names bus service path interface 
&optional name
 Return a list of all annotation names as list of strings.  If
 @var{name} is @code{nil}, the annotations are children of
@@ -928,6 +1008,10 @@
 @code{:byte ?x} is equal to @code{:byte ?\M-x}, but it is not equal to
 @code{:byte ?\C-x} or @code{:byte ?\M-\C-x}.
 
+Signed and unsigned integer D-Bus types expect a corresponding integer
+value.  If the value does not fit Emacs's integer range, it is also
+possible to use an equivalent floating point number.
+
 A D-Bus compound type is always represented as a list.  The @sc{car}
 of this list can be the type symbol @code{:array}, @code{:variant},
 @code{:struct} or @code{:dict-entry}, which would result in a
@@ -1182,24 +1266,6 @@
 @end lisp
 @end defun
 
address@hidden dbus-call-method-non-blocking bus service path interface method 
&optional :timeout timeout &rest args
-Call @var{method} on the D-Bus @var{bus}, but don't block the event queue.
-This is necessary for communicating to registered D-Bus methods,
-which are running in the same Emacs process.
-
-The arguments are the same as in @code{dbus-call-method}.  Example:
-
address@hidden
-(dbus-call-method-non-blocking
-  :system "org.freedesktop.Hal"
-  "/org/freedesktop/Hal/devices/computer"
-  "org.freedesktop.Hal.Device" "GetPropertyString"
-  "system.kernel.machine")
-
address@hidden "i686"
address@hidden lisp
address@hidden defun
-
 
 @node Asynchronous Methods
 @chapter Calling methods non-blocking.
@@ -1229,7 +1295,7 @@
 They are converted into D-Bus types as described in @ref{Type
 Conversion}.
 
-Unless @var{handler} is @code{nil}, the function returns a key into
+If @var{handler} is a Lisp function, the function returns a key into
 the hash table @code{dbus-registered-objects-table}.  The
 corresponding entry in the hash table is removed, when the return
 message has been arrived, and @var{handler} is called.  Example:
@@ -1241,7 +1307,7 @@
   "org.freedesktop.Hal.Device" "GetPropertyString" 'message
   "system.kernel.machine")
 
address@hidden (:system 2)
address@hidden (:serial :system 2)
 
 @print{} i686
 @end lisp
@@ -1323,19 +1389,21 @@
 
 It could be also an implementation of an own interface.  In this case,
 the service name must be @samp{org.gnu.Emacs}.  The object path shall
-begin with @samp{/org/gnu/Emacs/@strong{Application}/}, and the
+begin with @samp{/org/gnu/Emacs/@strong{Application}}, and the
 interface name shall be @address@hidden
 @address@hidden is the name of the application which
 provides the interface.
 
 @deffn Constant dbus-service-emacs
-The well known service name of Emacs.
+The well known service name @samp{org.gnu.Emacs} of Emacs.
 @end deffn
 
 @deffn 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.
+The object path namespace @samp{/org/gnu/Emacs} used by Emacs.
address@hidden deffn
+
address@hidden Constant dbus-interface-emacs
+The interface namespace @code{org.gnu.Emacs} used by Emacs.
 @end deffn
 
 @defun dbus-register-method bus service path interface method handler 
dont-register-service
@@ -1400,7 +1468,7 @@
   "org.freedesktop.TextEditor" "OpenFile"
   'my-dbus-method-handler)
 
address@hidden ((:session "org.freedesktop.TextEditor" "OpenFile")
address@hidden ((:method :session "org.freedesktop.TextEditor" "OpenFile")
     ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
      my-dbus-method-handler))
 @end lisp
@@ -1497,14 +1565,14 @@
   :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
   "org.freedesktop.TextEditor" "name" :read "GNU Emacs")
 
address@hidden ((:session "org.freedesktop.TextEditor" "name")
address@hidden ((: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)
 
address@hidden ((:session "org.freedesktop.TextEditor" "version")
address@hidden ((:property :session "org.freedesktop.TextEditor" "version")
     ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"))
 @end lisp
 
@@ -1569,8 +1637,8 @@
 @chapter Sending and receiving signals.
 @cindex signals
 
-Signals are broadcast messages.  They carry input parameters, which
-are received by all objects which have registered for such a signal.
+Signals are one way messages.  They carry input parameters, which are
+received by all objects which have registered for such a signal.
 
 @defun dbus-send-signal bus service path interface signal &rest args
 This function is similar to @code{dbus-call-method}.  The difference
@@ -1580,10 +1648,14 @@
 either the symbol @code{:system} or the symbol @code{:session}.  It
 doesn't matter whether another object has registered for @var{signal}.
 
address@hidden is the D-Bus service name of the object the signal is
-emitted from.  @var{path} is the corresponding D-Bus object path,
address@hidden is registered at.  @var{interface} is an interface
-offered by @var{service}.  It must provide @var{signal}.
+Signals can be unicast or broadcast messages.  For broadcast messages,
address@hidden must be @code{nil}.  Otherwise, @var{service} is the
+D-Bus service name the signal is sent to as unicast
address@hidden backward compatibility, a broadcast message is
+also emitted if @var{service} is the known or unique name Emacs is
+registered at D-Bus @var{bus}.}  @var{path} is the D-Bus object path
address@hidden is sent from.  @var{interface} is an interface available
+at @var{path}.  It must provide @var{signal}.
 
 All other arguments args are passed to @var{signal} as arguments.
 They are converted into D-Bus types as described in @ref{Type
@@ -1591,15 +1663,15 @@
 
 @lisp
 (dbus-send-signal
-  :session dbus-service-emacs dbus-path-emacs
-  (concat dbus-service-emacs ".FileManager") "FileModified"
+  :session nil dbus-path-emacs
+  (concat dbus-interface-emacs ".FileManager") "FileModified"
   "/home/albinus/.emacs")
 @end lisp
 @end defun
 
 @defun dbus-register-signal bus service path interface signal handler &rest 
args
-With this function, an application registers for @var{signal} on the
-D-Bus @var{bus}.
+With this function, an application registers for a signal on the D-Bus
address@hidden
 
 @var{bus} is either the symbol @code{:system} or the symbol
 @code{:session}.
@@ -1611,24 +1683,46 @@
 When the corresponding D-Bus object disappears, signals won't be
 received any longer.
 
-When @var{service} is @code{nil}, related signals from all D-Bus
-objects shall be accepted.
-
 @var{path} is the corresponding D-Bus object path, @var{service} is
-registered at.  It can also be @code{nil} if the path name of incoming
-signals shall not be checked.
+registered at.  @var{interface} is an interface offered by
address@hidden  It must provide @var{signal}.
 
address@hidden is an interface offered by @var{service}.  It must
-provide @var{signal}.
address@hidden, @var{path}, @var{interface} and @var{signal} can be
address@hidden  This is interpreted as a wildcard for the respective
+argument.
 
 @var{handler} is a Lisp function to be called when the @var{signal} is
 received.  It must accept as arguments the output parameters
 @var{signal} is sending.
 
-All other arguments @var{args}, if specified, must be strings.  They
-stand for the respective arguments of @var{signal} in their order, and
-are used for filtering as well.  A @code{nil} argument might be used
-to preserve the order.
+The remaining arguments @var{args} can be keywords or keyword string
address@hidden backward compatibility, the arguments @var{args}
+can also be just strings.  They stand for the respective arguments of
address@hidden in their order, and are used for filtering as well.  A
address@hidden argument might be used to preserve the order.}  The meaning
+is as follows:
+
address@hidden
address@hidden @code{:argN} @var{string}:@*
address@hidden:pathN} @var{string}:@*
+This stands for the Nth argument of the signal.  @code{:pathN}
+arguments can be used for object path wildcard matches as specified by
+D-Bus, whilest an @code{:argN} argument requires an exact match.
+
address@hidden @code{:arg-namespace} @var{string}:@*
+Register for the signals, which first argument defines the service or
+interface namespace @var{string}.
+
address@hidden @code{:path-namespace} @var{string}:@*
+Register for the object path namespace @var{string}.  All signals sent
+from an object path, which has @var{string} as the preceding string,
+are matched.  This requires @var{path} to be @code{nil}.
+
address@hidden @code{:eavesdrop}:@*
+Register for unicast signals which are not directed to the D-Bus
+object Emacs is registered at D-Bus BUS, if the security policy of BUS
+allows this.  Otherwise, this argument is ignored.
address@hidden itemize
 
 @code{dbus-register-signal} returns a Lisp object, which can be used
 as argument in @code{dbus-unregister-object} for removing the
@@ -1645,7 +1739,7 @@
   "org.freedesktop.Hal.Manager" "DeviceAdded"
   'my-dbus-signal-handler)
 
address@hidden ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
address@hidden ((:signal :system "org.freedesktop.Hal.Manager" "DeviceAdded")
     ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
      my-signal-handler))
 @end lisp
@@ -1657,23 +1751,36 @@
 single string argument therefore.  Plugging an USB device to your
 machine, when registered for signal @samp{DeviceAdded}, will show you
 which objects the GNU/Linux @code{hal} daemon adds.
+
+Some of the match rules have been added to a later version of D-Bus.
+In order to test the availability of such features, you could register
+for a dummy signal, and check the result:
+
address@hidden
+(dbus-ignore-errors
+  (dbus-register-signal
+    :system nil nil nil nil 'ignore :path-namespace "/invalid/path"))
+
address@hidden nil
address@hidden lisp
 @end defun
 
 
 @node Alternative Buses
address@hidden Alternative buses.
address@hidden Alternative buses and environments.
 @cindex bus names
 @cindex UNIX domain socket
address@hidden TCP/IP socket
 
 Until now, we have spoken about the system and the session buses,
 which are the default buses to be connected to.  However, it is
 possible to connect to any bus, from which the address is known.  This
-is a UNIX domain socket.  Everywhere, where a @var{bus} is mentioned
-as argument of a function (the symbol @code{:system} or the symbol
address@hidden:session}), this address can be used instead.  The connection to
-this bus must be initialized first.
+is a UNIX domain or TCP/IP socket.  Everywhere, where a @var{bus} is
+mentioned as argument of a function (the symbol @code{:system} or the
+symbol @code{:session}), this address can be used instead.  The
+connection to this bus must be initialized first.
 
address@hidden dbus-init-bus bus
address@hidden dbus-init-bus bus &optional private
 Establish the connection to D-Bus @var{bus}.
 
 @var{bus} can be either the symbol @code{:system} or the symbol
@@ -1682,30 +1789,90 @@
 is called when loading @file{dbus.el}, there is no need to call it
 again.
 
-Example: You open another session bus in a terminal window on your host:
-
address@hidden
-# eval `dbus-launch --auto-syntax`
-# echo $DBUS_SESSION_BUS_ADDRESS
-
address@hidden unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e
address@hidden example
-
-In Emacs, you can access to this bus via its address:
+The function returns a number, which counts the connections this Emacs
+session has established to the @var{bus} under the same unique name
+(see @code{dbus-get-unique-name}).  It depends on the libraries Emacs
+is linked with, and on the environment Emacs is running.  For example,
+if Emacs is linked with the gtk toolkit, and it runs in a GTK-aware
+environment like Gnome, another connection might already be
+established.
+
+When @var{private} is address@hidden, a new connection is established
+instead of reusing an existing one.  It results in a new unique name
+at the bus.  This can be used, if it is necessary to distinguish from
+another connection used in the same Emacs process, like the one
+established by GTK+.  It should be used with care for at least the
address@hidden:system} and @code{:session} buses, because other Emacs Lisp
+packages might already use this connection to those buses.
+
+Example: You initialize a connection to the AT-SPI bus on your host:
 
 @lisp
 (setq my-bus
-      "unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e")
-
address@hidden "unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e"
-
-(dbus-init-bus my-bus)
+  (dbus-call-method
+   :session "org.a11y.Bus" "/org/a11y/bus"
+   "org.a11y.Bus" "GetAddress"))
+
address@hidden 
"unix:abstract=/tmp/dbus-2yzWHOCdSD,guid=a490dd26625870ca1298b6e10000fd7f"
+
+;; If Emacs is built with gtk support, and you run in a GTK enabled
+;; environment (like a GNOME session), the initialization reuses the
+;; connection established by GTK's atk bindings.
+(dbus-init-bus my-bus)
+
address@hidden 2
+
+(dbus-get-unique-name my-bus)
+
address@hidden ":1.19"
+
+;; Open a new connection to the same bus.  This obsoletes the
+;; previous one.
+(dbus-init-bus my-bus 'private)
+
address@hidden 1
+
+(dbus-get-unique-name my-bus)
+
address@hidden ":1.20"
address@hidden lisp
+
+D-Bus addresses can specify different transport.  A possible address
+could be based on TCP/IP sockets, see next example.  However, it
+depends on the bus daemon configuration, which transport is supported.
address@hidden defun
+
address@hidden dbus-setenv bus variable value
+Set the value of the @var{bus} environment variable @var{variable} to
address@hidden
+
address@hidden is either a Lisp symbol, @code{:system} or @code{:session},
+or a string denoting the bus address.  Both @var{variable} and
address@hidden should be strings.
+
+Normally, services inherit the environment of the bus daemon.  This
+function adds to or modifies that environment when activating services.
+
+Some bus instances, such as @code{:system}, may disable setting the
+environment.  In such cases, or if this feature is not available in
+older D-Bus versions, a @code{dbus-error} error is raised.
+
+As an example, it might be desirable to start X11 enabled services on
+a remote host's bus on the same X11 server the local Emacs is
+running.  This could be achieved by
+
address@hidden
+(setq my-bus "unix:host=example.gnu.org,port=4711")
+
address@hidden "unix:host=example.gnu.org,port=4711"
+
+(dbus-init-bus my-bus)
+
address@hidden 1
+
+(dbus-setenv my-bus "DISPLAY" (getenv "DISPLAY"))
 
 @result{} nil
-
-(dbus-get-unique-name my-bus)
-
address@hidden ":1.0"
 @end lisp
 @end defun
 
@@ -1723,8 +1890,8 @@
 @end defvar
 
 Input parameters of @code{dbus-call-method},
address@hidden,
address@hidden, and
address@hidden, @code{dbus-send-signal},
address@hidden, @code{dbus-register-property} and
 @code{dbus-register-signal} are checked for correct D-Bus types. If
 there is a type mismatch, the Lisp error @code{wrong-type-argument}
 @code{D-Bus ARG} is raised.
@@ -1825,7 +1992,7 @@
 
 @lisp
 (defun my-dbus-event-error-handler (event error)
-  (when (string-equal (concat dbus-service-emacs ".FileManager")
+  (when (string-equal (concat dbus-interface-emacs ".FileManager")
                       (dbus-event-interface-name event))
     (message "my-dbus-event-error-handler: %S %S" event error)
     (signal 'file-error (cdr error))))

=== modified file 'etc/NEWS'
--- a/etc/NEWS  2012-04-22 13:58:00 +0000
+++ b/etc/NEWS  2012-04-22 14:11:43 +0000
@@ -91,6 +91,36 @@
 
 ** which-function-mode now applies to all applicable major modes by default.
 
+** D-Bus
+
++++
+*** New variables `dbus-compiled-version' and `dbus-runtime-version'.
+
++++
+*** The D-Bus object manager interface is implemented.
+
++++
+*** Variables of type :(u)int32 and :(u)int64 accept floating points,
+if their value does not fit into Emacs's integer range.
+
++++
+*** The function `dbus-call-method' works non-blocking now, it can be
+interrupted by C-g.  `dbus-call-method-non-blocking' is obsolete.
+
++++
+*** Signals can be sent also as unicast message.
+
++++
+*** The argument list of `dbus-register-signal' has been extended,
+according to the new match rule types of D-Bus.  See the manual for
+details.
+
++++
+*** `dbus-init-bus' supports private connections.
+
++++
+*** There is a new function `dbus-setenv'.
+
 ** Obsolete packages:
 
 *** mailpost.el

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-04-22 13:58:00 +0000
+++ b/lisp/ChangeLog    2012-04-22 14:11:43 +0000
@@ -1,3 +1,36 @@
+2012-04-22  Michael Albinus  <address@hidden>
+
+       Move functions from C to Lisp.  Make non-blocking method calls
+       the default.  Implement further D-Bus standard interfaces.
+
+       * net/dbus.el (dbus-message-internal): Declare function.  Remove
+       unneeded function declarations.
+       (defvar dbus-message-type-invalid, dbus-message-type-method-call)
+       (dbus-message-type-method-return, dbus-message-type-error)
+       (dbus-message-type-signal): Declare variables.  Remove local
+       definitions.
+       (dbus-interface-dbus, dbus-interface-peer)
+       (dbus-interface-introspectable, dbus-interface-properties)
+       (dbus-path-emacs, dbus-interface-emacs, dbus-return-values-table):
+       Adapt docstring.
+       (dbus-interface-objectmanager): New defconst.
+       (dbus-call-method, dbus-call-method-asynchronously)
+       (dbus-send-signal, dbus-method-return-internal)
+       (dbus-method-error-internal, dbus-register-service)
+       (dbus-register-signal, dbus-register-method): New defuns, moved
+       from dbusbind.c
+       (dbus-call-method-handler, dbus-setenv)
+       (dbus-get-all-managed-objects, dbus-managed-objects-handler): New
+       defuns.
+       (dbus-call-method-non-blocking): Make it an obsolete function.
+       (dbus-unregister-object, dbus-unregister-service)
+       (dbus-handle-event, dbus-register-property)
+       (dbus-property-handler): Obey the new structure of
+       `bus-registered-objects'.
+       (dbus-introspect): Use `dbus-call-method'.  Use a timeout.
+       (dbus-get-property, dbus-set-property, dbus-get-all-properties):
+       Use `dbus-call-method'.
+
 2012-04-22  Chong Yidong  <address@hidden>
 
        * cus-edit.el (custom-commands, custom-reset-menu)

=== modified file 'lisp/net/dbus.el'
--- a/lisp/net/dbus.el  2012-04-19 17:20:26 +0000
+++ b/lisp/net/dbus.el  2012-04-22 14:11:43 +0000
@@ -28,19 +28,19 @@
 
 ;; Low-level language bindings are implemented in src/dbusbind.c.
 
+;; D-Bus support in the Emacs core can be disabled with configuration
+;; option "--without-dbus".
+
 ;;; Code:
 
-;; D-Bus support in the Emacs core can be disabled with configuration
-;; option "--without-dbus".  Declare used subroutines and variables.
-(declare-function dbus-call-method "dbusbind.c")
-(declare-function dbus-call-method-asynchronously "dbusbind.c")
+;; Declare used subroutines and variables.
+(declare-function dbus-message-internal "dbusbind.c")
 (declare-function dbus-init-bus "dbusbind.c")
-(declare-function dbus-method-return-internal "dbusbind.c")
-(declare-function dbus-method-error-internal "dbusbind.c")
-(declare-function dbus-register-service "dbusbind.c")
-(declare-function dbus-register-signal "dbusbind.c")
-(declare-function dbus-register-method "dbusbind.c")
-(declare-function dbus-send-signal "dbusbind.c")
+(defvar dbus-message-type-invalid)
+(defvar dbus-message-type-method-call)
+(defvar dbus-message-type-method-return)
+(defvar dbus-message-type-error)
+(defvar dbus-message-type-signal)
 (defvar dbus-debug)
 (defvar dbus-registered-objects-table)
 
@@ -56,39 +56,93 @@
 (defconst dbus-path-dbus "/org/freedesktop/DBus"
   "The object path used to talk to the bus itself.")
 
+;; Default D-Bus interfaces.
+
 (defconst dbus-interface-dbus "org.freedesktop.DBus"
-  "The interface exported by the object with `dbus-service-dbus' and 
`dbus-path-dbus'.")
+  "The interface exported by the service `dbus-service-dbus'.")
 
 (defconst dbus-interface-peer (concat dbus-interface-dbus ".Peer")
-  "The interface for peer objects.")
+  "The interface for peer objects.
+See URL 
`http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-peer'.")
+
+;; <interface name="org.freedesktop.DBus.Peer">
+;;   <method name="Ping">
+;;   </method>
+;;   <method name="GetMachineId">
+;;     <arg name="machine_uuid" type="s" direction="out"/>
+;;   </method>
+;; </interface>
 
 (defconst dbus-interface-introspectable
   (concat dbus-interface-dbus ".Introspectable")
-  "The interface supported by introspectable objects.")
+  "The interface supported by introspectable objects.
+See URL 
`http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable'.")
+
+;; <interface name="org.freedesktop.DBus.Introspectable">
+;;   <method name="Introspect">
+;;     <arg name="data" type="s" direction="out"/>
+;;   </method>
+;; </interface>
 
 (defconst dbus-interface-properties (concat dbus-interface-dbus ".Properties")
-  "The interface for property objects.")
-
+  "The interface for property objects.
+See URL 
`http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties'.")
+
+;; <interface name="org.freedesktop.DBus.Properties">
+;;   <method name="Get">
+;;     <arg name="interface" type="s" direction="in"/>
+;;     <arg name="propname"  type="s" direction="in"/>
+;;     <arg name="value"     type="v" direction="out"/>
+;;   </method>
+;;   <method name="Set">
+;;     <arg name="interface" type="s" direction="in"/>
+;;     <arg name="propname"  type="s" direction="in"/>
+;;     <arg name="value"     type="v" direction="in"/>
+;;   </method>
+;;   <method name="GetAll">
+;;     <arg name="interface" type="s" direction="in"/>
+;;     <arg name="props"     type="a{sv}" direction="out"/>
+;;   </method>
+;;   <signal name="PropertiesChanged">
+;;     <arg name="interface" type="s"/>
+;;     <arg name="changed_properties"     type="a{sv}"/>
+;;     <arg name="invalidated_properties" type="as"/>
+;;   </signal>
+;; </interface>
+
+(defconst dbus-interface-objectmanager
+  (concat dbus-interface-dbus ".ObjectManager")
+  "The object manager interface.
+See URL 
`http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager'.")
+
+;; <interface name="org.freedesktop.DBus.ObjectManager">
+;;   <method name="GetManagedObjects">
+;;     <arg name="object_paths_interfaces_and_properties"
+;;          type="a{oa{sa{sv}}}" direction="out"/>
+;;   </method>
+;;   <signal name="InterfacesAdded">
+;;     <arg name="object_path"               type="o"/>
+;;     <arg name="interfaces_and_properties" type="a{sa{sv}}"/>
+;;   </signal>
+;;   <signal name="InterfacesRemoved">
+;;     <arg name="object_path"               type="o"/>
+;;     <arg name="interfaces"                type="as"/>
+;;   </signal>
+;; </interface>
+
+;; Emacs defaults.
 (defconst dbus-service-emacs "org.gnu.Emacs"
   "The well known service name of Emacs.")
 
 (defconst dbus-path-emacs "/org/gnu/Emacs"
-  "The object path head used by Emacs.")
-
-(defconst dbus-message-type-invalid 0
-  "This value is never a valid message type.")
-
-(defconst dbus-message-type-method-call 1
-  "Message type of a method call message.")
-
-(defconst dbus-message-type-method-return 2
-  "Message type of a method return message.")
-
-(defconst dbus-message-type-error 3
-  "Message type of an error reply message.")
-
-(defconst dbus-message-type-signal 4
-  "Message type of a signal message.")
+  "The object path namespace used by Emacs.
+All object paths provided by the service `dbus-service-emacs'
+shall be subdirectories of this path.")
+
+(defconst dbus-interface-emacs "org.gnu.Emacs"
+  "The interface namespace used by Emacs.")
+
+;; D-Bus constants.
 
 (defmacro dbus-ignore-errors (&rest body)
   "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil.
@@ -105,15 +159,267 @@
 caught in `condition-case' by `dbus-error'.")
 
 
-;;; Hash table of registered functions.
+;;; Basic D-Bus message functions.
 
 (defvar dbus-return-values-table (make-hash-table :test 'equal)
   "Hash table for temporary storing arguments of reply messages.
-A key in this hash table is a list (BUS SERIAL).  BUS is either a
-Lisp symbol, `:system' or `:session', or a string denoting the
-bus address.  SERIAL is the serial number of the reply message.
-See `dbus-call-method-non-blocking-handler' and
-`dbus-call-method-non-blocking'.")
+A key in this hash table is a list (:serial BUS SERIAL), like in
+`dbus-registered-objects-table'.  BUS is either a Lisp symbol,
+`:system' or `:session', or a string denoting the bus address.
+SERIAL is the serial number of the reply message.")
+
+(defun dbus-call-method-handler (&rest args)
+  "Handler for reply messages of asynchronous D-Bus message calls.
+It calls the function stored in `dbus-registered-objects-table'.
+The result will be made available in `dbus-return-values-table'."
+  (puthash (list  :serial
+                 (dbus-event-bus-name last-input-event)
+                (dbus-event-serial-number last-input-event))
+          (if (= (length args) 1) (car args) args)
+          dbus-return-values-table))
+
+(defun dbus-call-method (bus service path interface method &rest args)
+  "Call METHOD on the D-Bus BUS.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.
+
+SERVICE is the D-Bus service name to be used.  PATH is the D-Bus
+object path SERVICE is registered at.  INTERFACE is an interface
+offered by SERVICE.  It must provide METHOD.
+
+If the parameter `:timeout' is given, the following integer TIMEOUT
+specifies the maximum number of milliseconds the method call must
+return.  The default value is 25,000.  If the method call doesn't
+return in time, a D-Bus error is raised.
+
+All other arguments ARGS are passed to METHOD as arguments.  They are
+converted into D-Bus types via the following rules:
+
+  t and nil => DBUS_TYPE_BOOLEAN
+  number    => DBUS_TYPE_UINT32
+  integer   => DBUS_TYPE_INT32
+  float     => DBUS_TYPE_DOUBLE
+  string    => DBUS_TYPE_STRING
+  list      => DBUS_TYPE_ARRAY
+
+All arguments can be preceded by a type symbol.  For details about
+type symbols, see Info node `(dbus)Type Conversion'.
+
+`dbus-call-method' returns the resulting values of METHOD as a list of
+Lisp objects.  The type conversion happens the other direction as for
+input arguments.  It follows the mapping rules:
+
+  DBUS_TYPE_BOOLEAN     => t or nil
+  DBUS_TYPE_BYTE        => number
+  DBUS_TYPE_UINT16      => number
+  DBUS_TYPE_INT16       => integer
+  DBUS_TYPE_UINT32      => number or float
+  DBUS_TYPE_UNIX_FD     => number or float
+  DBUS_TYPE_INT32       => integer or float
+  DBUS_TYPE_UINT64      => number or float
+  DBUS_TYPE_INT64       => integer or float
+  DBUS_TYPE_DOUBLE      => float
+  DBUS_TYPE_STRING      => string
+  DBUS_TYPE_OBJECT_PATH => string
+  DBUS_TYPE_SIGNATURE   => string
+  DBUS_TYPE_ARRAY       => list
+  DBUS_TYPE_VARIANT     => list
+  DBUS_TYPE_STRUCT      => list
+  DBUS_TYPE_DICT_ENTRY  => list
+
+Example:
+
+\(dbus-call-method
+  :session \"org.gnome.seahorse\" \"/org/gnome/seahorse/keys/openpgp\"
+  \"org.gnome.seahorse.Keys\" \"GetKeyField\"
+  \"openpgp:657984B8C7A966DD\" \"simple-name\")
+
+  => (t (\"Philip R. Zimmermann\"))
+
+If the result of the METHOD call is just one value, the converted Lisp
+object is returned instead of a list containing this single Lisp object.
+
+\(dbus-call-method
+  :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/devices/computer\"
+  \"org.freedesktop.Hal.Device\" \"GetPropertyString\"
+  \"system.kernel.machine\")
+
+  => \"i686\""
+
+  (or (memq bus '(:system :session)) (stringp bus)
+      (signal 'wrong-type-argument (list 'keywordp bus)))
+  (or (stringp service)
+      (signal 'wrong-type-argument (list 'stringp service)))
+  (or (stringp path)
+      (signal 'wrong-type-argument (list 'stringp path)))
+  (or (stringp interface)
+      (signal 'wrong-type-argument (list 'stringp interface)))
+  (or (stringp method)
+      (signal 'wrong-type-argument (list 'stringp method)))
+
+  (let ((timeout (plist-get args :timeout))
+       (key
+        (apply
+         'dbus-message-internal dbus-message-type-method-call
+         bus service path interface method 'dbus-call-method-handler args)))
+    ;; Wait until `dbus-call-method-handler' has put the result into
+    ;; `dbus-return-values-table'.  If no timeout is given, use the
+    ;; default 25".
+    (with-timeout ((if timeout (/ timeout 1000.0) 25))
+      (while (eq (gethash key dbus-return-values-table :ignore) :ignore)
+       (read-event nil nil 0.1)))
+
+    ;; Cleanup `dbus-return-values-table'.  Return the result.
+    (prog1
+       (gethash key dbus-return-values-table)
+      (remhash key dbus-return-values-table))))
+
+;; `dbus-call-method' works non-blocking now.
+(defalias 'dbus-call-method-non-blocking 'dbus-call-method)
+(make-obsolete 'dbus-call-method-non-blocking 'dbus-call-method "24.2")
+
+(defun dbus-call-method-asynchronously
+ (bus service path interface method handler &rest args)
+ "Call METHOD on the D-Bus BUS asynchronously.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.
+
+SERVICE is the D-Bus service name to be used.  PATH is the D-Bus
+object path SERVICE is registered at.  INTERFACE is an interface
+offered by SERVICE.  It must provide METHOD.
+
+HANDLER is a Lisp function, which is called when the corresponding
+return message has arrived.  If HANDLER is nil, no return message
+will be expected.
+
+If the parameter `:timeout' is given, the following integer TIMEOUT
+specifies the maximum number of milliseconds the method call must
+return.  The default value is 25,000.  If the method call doesn't
+return in time, a D-Bus error is raised.
+
+All other arguments ARGS are passed to METHOD as arguments.  They are
+converted into D-Bus types via the following rules:
+
+  t and nil => DBUS_TYPE_BOOLEAN
+  number    => DBUS_TYPE_UINT32
+  integer   => DBUS_TYPE_INT32
+  float     => DBUS_TYPE_DOUBLE
+  string    => DBUS_TYPE_STRING
+  list      => DBUS_TYPE_ARRAY
+
+All arguments can be preceded by a type symbol.  For details about
+type symbols, see Info node `(dbus)Type Conversion'.
+
+If HANDLER is a Lisp function, the function returns a key into the
+hash table `dbus-registered-objects-table'.  The corresponding entry
+in the hash table is removed, when the return message has been arrived,
+and HANDLER is called.
+
+Example:
+
+\(dbus-call-method-asynchronously
+  :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/devices/computer\"
+  \"org.freedesktop.Hal.Device\" \"GetPropertyString\" 'message
+  \"system.kernel.machine\")
+
+  => \(:serial :system 2)
+
+  -| i686"
+
+  (or (memq bus '(:system :session)) (stringp bus)
+      (signal 'wrong-type-argument (list 'keywordp bus)))
+  (or (stringp service)
+      (signal 'wrong-type-argument (list 'stringp service)))
+  (or (stringp path)
+      (signal 'wrong-type-argument (list 'stringp path)))
+  (or (stringp interface)
+      (signal 'wrong-type-argument (list 'stringp interface)))
+  (or (stringp method)
+      (signal 'wrong-type-argument (list 'stringp method)))
+  (or (null handler) (functionp handler)
+      (signal 'wrong-type-argument (list 'functionp handler)))
+
+  (apply 'dbus-message-internal dbus-message-type-method-call
+        bus service path interface method handler args))
+
+(defun dbus-send-signal (bus service path interface signal &rest args)
+  "Send signal SIGNAL on the D-Bus BUS.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.  The signal is sent from the D-Bus object
+Emacs is registered at BUS.
+
+SERVICE is the D-Bus name SIGNAL is sent to.  It can be either a known
+name or a unique name.  If SERVICE is nil, the signal is sent as
+broadcast message.  PATH is the D-Bus object path SIGNAL is sent from.
+INTERFACE is an interface available at PATH.  It must provide signal
+SIGNAL.
+
+All other arguments ARGS are passed to SIGNAL as arguments.  They are
+converted into D-Bus types via the following rules:
+
+  t and nil => DBUS_TYPE_BOOLEAN
+  number    => DBUS_TYPE_UINT32
+  integer   => DBUS_TYPE_INT32
+  float     => DBUS_TYPE_DOUBLE
+  string    => DBUS_TYPE_STRING
+  list      => DBUS_TYPE_ARRAY
+
+All arguments can be preceded by a type symbol.  For details about
+type symbols, see Info node `(dbus)Type Conversion'.
+
+Example:
+
+\(dbus-send-signal
+  :session nil \"/org/gnu/Emacs\" \"org.gnu.Emacs.FileManager\"
+  \"FileModified\" \"/home/albinus/.emacs\")"
+
+  (or (memq bus '(:system :session)) (stringp bus)
+      (signal 'wrong-type-argument (list 'keywordp bus)))
+  (or (null service) (stringp service)
+      (signal 'wrong-type-argument (list 'stringp service)))
+  (or (stringp path)
+      (signal 'wrong-type-argument (list 'stringp path)))
+  (or (stringp interface)
+      (signal 'wrong-type-argument (list 'stringp interface)))
+  (or (stringp signal)
+      (signal 'wrong-type-argument (list 'stringp signal)))
+
+  (apply 'dbus-message-internal dbus-message-type-signal
+        bus service path interface signal args))
+
+(defun dbus-method-return-internal (bus service serial &rest args)
+  "Return for message SERIAL on the D-Bus BUS.
+This is an internal function, it shall not be used outside dbus.el."
+
+  (or (memq bus '(:system :session)) (stringp bus)
+      (signal 'wrong-type-argument (list 'keywordp bus)))
+  (or (stringp service)
+      (signal 'wrong-type-argument (list 'stringp service)))
+  (or (natnump serial)
+      (signal 'wrong-type-argument (list 'natnump serial)))
+
+  (apply 'dbus-message-internal dbus-message-type-method-return
+        bus service serial args))
+
+(defun dbus-method-error-internal (bus service serial &rest args)
+  "Return error message for message SERIAL on the D-Bus BUS.
+This is an internal function, it shall not be used outside dbus.el."
+
+  (or (memq bus '(:system :session)) (stringp bus)
+      (signal 'wrong-type-argument (list 'keywordp bus)))
+  (or (stringp service)
+      (signal 'wrong-type-argument (list 'stringp service)))
+  (or (natnump serial)
+      (signal 'wrong-type-argument (list 'natnump serial)))
+
+  (apply 'dbus-message-internal dbus-message-type-error
+        bus service serial args))
+
+
+;;; Hash table of registered functions.
 
 (defun dbus-list-hash-table ()
   "Returns all registered member registrations to D-Bus.
@@ -126,6 +432,313 @@
      dbus-registered-objects-table)
     result))
 
+(defun dbus-setenv (bus variable value)
+  "Set the value of the BUS environment variable named VARIABLE to VALUE.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.  Both VARIABLE and VALUE should be strings.
+
+Normally, services inherit the environment of the BUS daemon.  This
+function adds to or modifies that environment when activating services.
+
+Some bus instances, such as `:system', may disable setting the environment."
+  (dbus-call-method
+   bus dbus-service-dbus dbus-path-dbus
+   dbus-interface-dbus "UpdateActivationEnvironment"
+   `(:array (:dict-entry ,variable ,value))))
+
+(defun dbus-register-service (bus service &rest flags)
+  "Register known name SERVICE on the D-Bus BUS.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.
+
+SERVICE is the D-Bus service name that should be registered.  It must
+be a known name.
+
+FLAGS are keywords, which control how the service name is registered.
+The following keywords are recognized:
+
+`: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.
+
+The function returns a keyword, indicating the result of the
+operation.  One of the following keywords is returned:
+
+`:primary-owner': Service has become the primary owner of the
+requested name.
+
+`:in-queue': Service could not become the primary owner and has been
+placed in the queue.
+
+`:exists': Service is already in the queue.
+
+`:already-owner': Service is already the primary owner."
+
+  ;; Add ObjectManager handler.
+  (dbus-register-method
+   bus service nil dbus-interface-objectmanager "GetManagedObjects"
+   'dbus-managed-objects-handler 'dont-register)
+
+  (let ((arg 0)
+       reply)
+    (dolist (flag flags)
+      (setq arg
+           (+ arg
+              (case flag
+                (:allow-replacement 1)
+                (:replace-existing 2)
+                (:do-not-queue 4)
+                (t (signal 'wrong-type-argument (list flag)))))))
+    (setq reply (dbus-call-method
+                bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+                "RequestName" service arg))
+    (case reply
+      (1 :primary-owner)
+      (2 :in-queue)
+      (3 :exists)
+      (4 :already-owner)
+      (t (signal 'dbus-error (list "Could not register service" service))))))
+
+(defun dbus-unregister-service (bus service)
+  "Unregister all objects related to SERVICE from D-Bus BUS.
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.  SERVICE must be a known service name.
+
+The function returns a keyword, indicating the result of the
+operation.  One of the following keywords is returned:
+
+`:released': Service has become the primary owner of the name.
+
+`:non-existent': Service name does not exist on this bus.
+
+`:not-owner': We are neither the primary owner nor waiting in the
+queue of this service."
+
+  (maphash
+   (lambda (key value)
+     (dolist (elt value)
+       (ignore-errors
+        (when (and (equal bus (cadr key)) (string-equal service (cadr elt)))
+          (unless
+              (puthash key (delete elt value) dbus-registered-objects-table)
+            (remhash key dbus-registered-objects-table))))))
+   dbus-registered-objects-table)
+  (let ((reply (dbus-call-method
+               bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+               "ReleaseName" service)))
+    (case reply
+      (1 :released)
+      (2 :non-existent)
+      (3 :not-owner)
+      (t (signal 'dbus-error (list "Could not unregister service" service))))))
+
+(defun dbus-register-signal
+  (bus service path interface signal handler &rest args)
+  "Register for a signal on the D-Bus BUS.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.
+
+SERVICE is the D-Bus service name used by the sending D-Bus object.
+It can be either a known name or the unique name of the D-Bus object
+sending the signal.
+
+PATH is the D-Bus object path SERVICE is registered.  INTERFACE
+is an interface offered by SERVICE.  It must provide SIGNAL.
+HANDLER is a Lisp function to be called when the signal is
+received.  It must accept as arguments the values SIGNAL is
+sending.
+
+SERVICE, PATH, INTERFACE and SIGNAL can be nil.  This is
+interpreted as a wildcard for the respective argument.
+
+The remaining arguments ARGS can be keywords or keyword string pairs.
+The meaning is as follows:
+
+`:argN' STRING:
+`:pathN' STRING: This stands for the Nth argument of the
+signal.  `:pathN' arguments can be used for object path wildcard
+matches as specified by D-Bus, whilest an `:argN' argument
+requires an exact match.
+
+`:arg-namespace' STRING: Register for the signals, which first
+argument defines the service or interface namespace STRING.
+
+`:path-namespace' STRING: Register for the object path namespace
+STRING.  All signals sent from an object path, which has STRING as
+the preceding string, are matched.  This requires PATH to be nil.
+
+`:eavesdrop': Register for unicast signals which are not directed
+to the D-Bus object Emacs is registered at D-Bus BUS, if the
+security policy of BUS allows this.
+
+Example:
+
+\(defun my-signal-handler (device)
+  (message \"Device %s added\" device))
+
+\(dbus-register-signal
+  :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/Manager\"
+  \"org.freedesktop.Hal.Manager\" \"DeviceAdded\" 'my-signal-handler)
+
+  => \(\(:signal :system \"org.freedesktop.Hal.Manager\" \"DeviceAdded\")
+      \(\"org.freedesktop.Hal\" \"/org/freedesktop/Hal/Manager\" 
my-signal-handler))
+
+`dbus-register-signal' returns an object, which can be used in
+`dbus-unregister-object' for removing the registration."
+
+  (let ((counter 0)
+       (rule "type='signal'")
+       uname key key1 value)
+
+    ;; Retrieve unique name of service.  If service is a known name,
+    ;; we will register for the corresponding unique name, if any.
+    ;; Signals are sent always with the unique name as sender.  Note:
+    ;; the unique name of `dbus-service-dbus' is that string itself.
+    (if (and (stringp service)
+            (not (zerop (length service)))
+            (not (string-equal service dbus-service-dbus))
+            (not (string-match "^:" service)))
+       (setq uname (dbus-get-name-owner bus service))
+      (setq uname service))
+
+    (setq rule (concat rule
+                      (when uname (format ",sender='%s'" uname))
+                      (when interface (format ",interface='%s'" interface))
+                      (when signal (format ",member='%s'" signal))
+                      (when path (format ",path='%s'" path))))
+
+    ;; Add arguments to the rule.
+    (if (or (stringp (car args)) (null (car args)))
+       ;; As backward compatibility option, we allow just strings.
+       (dolist (arg args)
+         (if (stringp arg)
+             (setq rule (concat rule (format ",arg%d='%s'" counter arg)))
+           (if arg (signal 'wrong-type-argument (list "Wrong argument" arg))))
+         (setq counter (1+ counter)))
+
+      ;; Parse keywords.
+      (while args
+       (setq
+        key (car args)
+        rule (concat
+              rule
+              (cond
+               ;; `:arg0' .. `:arg63', `:path0' .. `:path63'.
+               ((and (keywordp key)
+                     (string-match
+                      "^:\\(arg\\|path\\)\\([[:digit:]]+\\)$"
+                      (symbol-name key)))
+                (setq counter (match-string 2 (symbol-name key))
+                      args (cdr args)
+                      value (car args))
+                (unless (and (<= counter 63) (stringp value))
+                  (signal 'wrong-type-argument
+                          (list "Wrong argument" key value)))
+                (format
+                 ",arg%s%s='%s'"
+                 counter
+                 (if (string-equal (match-string 1 (symbol-name key)) "path")
+                     "path" "")
+                 value))
+               ;; `:arg-namespace', `:path-namespace'.
+               ((and (keywordp key)
+                     (string-match
+                      "^:\\(arg\\|path\\)-namespace$" (symbol-name key)))
+                (setq args (cdr args)
+                      value (car args))
+                (unless (stringp value)
+                  (signal 'wrong-type-argument
+                          (list "Wrong argument" key value)))
+                (format
+                 ",%s='%s'"
+                 (if (string-equal (match-string 1 (symbol-name key)) "path")
+                     "path_namespace" "arg0namespace")
+                 value))
+               ;; `:eavesdrop'.
+               ((eq key :eavesdrop)
+                ",eavesdrop='true'")
+               (t (signal 'wrong-type-argument (list "Wrong argument" key)))))
+        args (cdr args))))
+
+    ;; Add the rule to the bus.
+    (condition-case err
+       (dbus-call-method
+        bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+        "AddMatch" rule)
+      (dbus-error
+       (if (not (string-match "eavesdrop" rule))
+          (signal (car err) (cdr err))
+        ;; The D-Bus spec says we shall fall back to a rule without eavesdrop.
+        (when dbus-debug (message "Removing eavesdrop from rule %s" rule))
+        (setq rule (replace-regexp-in-string ",eavesdrop='true'" "" rule))
+        (dbus-call-method
+         bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+         "AddMatch" rule))))
+
+    (when dbus-debug (message "Matching rule \"%s\" created" rule))
+
+    ;; Create a hash table entry.
+    (setq key (list :signal bus interface signal)
+         key1 (list uname service path handler rule)
+         value (gethash key dbus-registered-objects-table))
+    (unless  (member key1 value)
+      (puthash key (cons key1 value) dbus-registered-objects-table))
+
+    ;; Return the object.
+    (list key (list service path handler))))
+
+(defun dbus-register-method
+  (bus service path interface method handler &optional dont-register-service)
+  "Register for method METHOD on the D-Bus BUS.
+
+BUS is either a Lisp symbol, `:system' or `:session', or a string
+denoting the bus address.
+
+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 the input arguments of METHOD.  The return
+value of HANDLER is used for composing the returning D-Bus message.
+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."
+
+  ;; Register SERVICE.
+  (unless (or dont-register-service
+             (member service (dbus-list-names bus)))
+    (dbus-register-service bus service))
+
+  ;; Create a hash table entry.  We use nil for the unique name,
+  ;; because the method might be called from anybody.
+  (let* ((key (list :method bus interface method))
+        (key1 (list nil service path handler))
+        (value (gethash key dbus-registered-objects-table)))
+
+    (unless  (member key1 value)
+      (puthash key (cons key1 value) dbus-registered-objects-table))
+
+    ;; Return the object.
+    (list key (list service path handler))))
+
 (defun dbus-unregister-object (object)
   "Unregister OBJECT from D-Bus.
 OBJECT must be the result of a preceding `dbus-register-method',
@@ -141,12 +754,13 @@
 
   ;; Find the corresponding entry in the hash table.
   (let* ((key (car object))
+        (type (car key))
+        (bus (cadr key))
         (value (cadr object))
-        (bus (car key))
         (service (car value))
         (entry (gethash key dbus-registered-objects-table))
         ret)
-    ;; key has the structure (BUS INTERFACE MEMBER).
+    ;; key has the structure (TYPE BUS INTERFACE MEMBER).
     ;; value has the structure (SERVICE PATH [HANDLER]).
     ;; entry has the structure ((UNAME SERVICE PATH MEMBER [RULE]) ...).
     ;; MEMBER is either a string (the handler), or a cons cell (a
@@ -164,154 +778,35 @@
        (unless (puthash key (delete elt entry) dbus-registered-objects-table)
          (remhash key dbus-registered-objects-table))
        ;; Remove match rule of signals.
-       (let ((rule (nth 4 elt)))
-         (when (stringp rule)
-           (setq service nil) ; We do not need to unregister the service.
-           (dbus-call-method
-            bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-            "RemoveMatch" rule)))))
+       (when (eq type :signal)
+         (dbus-call-method
+          bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+          "RemoveMatch" (nth 4 elt)))))
+
     ;; Check, whether there is still a registered function or property
     ;; for the given service.  If not, unregister the service from the
     ;; bus.
-    (when service
-      (dolist (elt entry)
-       (let (found)
-         (maphash
-          (lambda (k v)
-            (dolist (e v)
-              (ignore-errors
-                (when (and (equal bus (car k)) (string-equal service (cadr e)))
-                  (setq found t)))))
-          dbus-registered-objects-table)
-         (unless found
-           (dbus-call-method
-            bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-            "ReleaseName" service)))))
+    (when (and service (memq type '(:method :property))
+              (not (catch :found
+                     (progn
+                       (maphash
+                        (lambda (k v)
+                          (dolist (e v)
+                            (ignore-errors
+                              (and
+                               ;; Bus.
+                               (equal bus (cadr k))
+                               ;; Service.
+                               (string-equal service (cadr e))
+                               ;; Non-empty object path.
+                               (caddr e)
+                               (throw :found t)))))
+                        dbus-registered-objects-table)
+                       nil))))
+      (dbus-unregister-service bus service))
     ;; Return.
     ret))
 
-(defun dbus-unregister-service (bus service)
-  "Unregister all objects related to SERVICE from D-Bus BUS.
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.  SERVICE must be a known service name.
-
-The function returns a keyword, indicating the result of the
-operation.  One of the following keywords is returned:
-
-`:released': Service has become the primary owner of the name.
-
-`:non-existent': Service name does not exist on this bus.
-
-`:not-owner': We are neither the primary owner nor waiting in the
-queue of this service."
-
-  (maphash
-   (lambda (key value)
-     (dolist (elt value)
-       (ignore-errors
-        (when (and (equal bus (car key)) (string-equal service (cadr elt)))
-          (unless
-              (puthash key (delete elt value) dbus-registered-objects-table)
-            (remhash key dbus-registered-objects-table))))))
-   dbus-registered-objects-table)
-  (let ((reply (dbus-call-method
-               bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-               "ReleaseName" service)))
-    (case reply
-      (1 :released)
-      (2 :non-existent)
-      (3 :not-owner)
-      (t (signal 'dbus-error (list "Could not unregister service" service))))))
-
-(defun dbus-call-method-non-blocking-handler (&rest args)
-  "Handler for reply messages of asynchronous D-Bus message calls.
-It calls the function stored in `dbus-registered-objects-table'.
-The result will be made available in `dbus-return-values-table'."
-  (puthash (list (dbus-event-bus-name last-input-event)
-                (dbus-event-serial-number last-input-event))
-          (if (= (length args) 1) (car args) args)
-          dbus-return-values-table))
-
-(defun dbus-call-method-non-blocking
-  (bus service path interface method &rest args)
-  "Call METHOD on the D-Bus BUS, but don't block the event queue.
-This is necessary for communicating to registered D-Bus methods,
-which are running in the same Emacs process.
-
-The arguments are the same as in `dbus-call-method'.
-
-usage: (dbus-call-method-non-blocking
-         BUS SERVICE PATH INTERFACE METHOD
-         &optional :timeout TIMEOUT &rest ARGS)"
-
-  (let ((key
-        (apply
-         'dbus-call-method-asynchronously
-         bus service path interface method
-         'dbus-call-method-non-blocking-handler args)))
-    ;; Wait until `dbus-call-method-non-blocking-handler' has put the
-    ;; result into `dbus-return-values-table'.
-    (while (eq (gethash key dbus-return-values-table :ignore) :ignore)
-      (read-event nil nil 0.1))
-
-    ;; Cleanup `dbus-return-values-table'.  Return the result.
-    (prog1
-       (gethash key dbus-return-values-table nil)
-      (remhash key dbus-return-values-table))))
-
-(defun dbus-name-owner-changed-handler (&rest args)
-  "Reapplies all member registrations to D-Bus.
-This handler is applied when a \"NameOwnerChanged\" signal has
-arrived.  SERVICE is the object name for which the name owner has
-been changed.  OLD-OWNER is the previous owner of SERVICE, or the
-empty string if SERVICE was not owned yet.  NEW-OWNER is the new
-owner of SERVICE, or the empty string if SERVICE loses any name owner.
-
-usage: (dbus-name-owner-changed-handler service old-owner new-owner)"
-  (save-match-data
-    ;; Check the arguments.  We should silently ignore it when they
-    ;; are wrong.
-    (if (and (= (length args) 3)
-            (stringp (car args))
-            (stringp (cadr args))
-            (stringp (caddr args)))
-       (let ((service (car args))
-             (old-owner (cadr args)))
-         ;; Check whether SERVICE is a known name.
-         (when (not (string-match "^:" service))
-           (maphash
-            (lambda (key value)
-               (dolist (elt value)
-                 ;; key has the structure (BUS INTERFACE MEMBER).
-                 ;; elt has the structure (UNAME SERVICE PATH HANDLER).
-                 (when (string-equal old-owner (car elt))
-                   ;; Remove old key, and add new entry with changed name.
-                   (dbus-unregister-object (list key (cdr elt)))
-                   ;; Maybe we could arrange the lists a little bit better
-                   ;; that we don't need to extract every single element?
-                   (dbus-register-signal
-                    ;; BUS      SERVICE     PATH
-                    (nth 0 key) (nth 1 elt) (nth 2 elt)
-                    ;; INTERFACE MEMBER     HANDLER
-                    (nth 1 key) (nth 2 key) (nth 3 elt)))))
-            (copy-hash-table dbus-registered-objects-table))))
-      ;; The error is reported only in debug mode.
-      (when  dbus-debug
-       (signal
-        'dbus-error
-        (cons
-         (format "Wrong arguments of %s.NameOwnerChanged" dbus-interface-dbus)
-         args))))))
-
-;; Register the handler.
-(when nil ;ignore-errors
-  (dbus-register-signal
-   :system dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-   "NameOwnerChanged" 'dbus-name-owner-changed-handler)
-  (dbus-register-signal
-   :session dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-   "NameOwnerChanged" 'dbus-name-owner-changed-handler))
-
 
 ;;; D-Bus type conversion.
 
@@ -437,9 +932,9 @@
          (dbus-ignore-errors
            (if (eq result :ignore)
                (dbus-method-return-internal
-                (nth 1 event) (nth 3 event) (nth 4 event))
+                (nth 1 event) (nth 4 event) (nth 3 event))
              (apply 'dbus-method-return-internal
-                    (nth 1 event) (nth 3 event) (nth 4 event)
+                    (nth 1 event) (nth 4 event) (nth 3 event)
                     (if (consp result) result (list result)))))))
     ;; Error handling.
     (dbus-error
@@ -447,7 +942,7 @@
      (when (= dbus-message-type-method-call (nth 2 event))
        (dbus-ignore-errors
         (dbus-method-error-internal
-         (nth 1 event) (nth 3 event) (nth 4 event) (cadr err))))
+         (nth 1 event) (nth 4 event) (nth 3 event) (cadr err))))
      ;; Propagate D-Bus error messages.
      (run-hook-with-args 'dbus-event-error-hooks event err)
      (when (or dbus-debug (= dbus-message-type-error (nth 2 event)))
@@ -596,11 +1091,11 @@
 XML format."
   ;; We don't want to raise errors.  `dbus-call-method-non-blocking'
   ;; is used, because the handler can be registered in our Emacs
-  ;; instance; caller an callee would block each other.
+  ;; instance; caller and callee would block each other.
   (dbus-ignore-errors
-    (funcall
-     (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking)
-     bus service path dbus-interface-introspectable "Introspect")))
+    (dbus-call-method
+     bus service path dbus-interface-introspectable "Introspect"
+     :timeout 1000)))
 
 (defun dbus-introspect-xml (bus service path)
   "Return the introspection data of SERVICE in D-Bus BUS at object path PATH.
@@ -854,12 +1349,11 @@
 It will be checked at BUS, SERVICE, PATH.  The result can be any
 valid D-Bus value, or `nil' if there is no PROPERTY."
   (dbus-ignore-errors
-    ;; "Get" returns a variant, so we must use the `car'.
-    (car
-     (funcall
-      (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking)
-      bus service path dbus-interface-properties
-      "Get" :timeout 500 interface property))))
+   ;; "Get" returns a variant, so we must use the `car'.
+   (car
+    (dbus-call-method
+     bus service path dbus-interface-properties
+     "Get" :timeout 500 interface property))))
 
 (defun dbus-set-property (bus service path interface property value)
   "Set value of PROPERTY of INTERFACE to VALUE.
@@ -867,13 +1361,12 @@
 been set successful, the result is VALUE.  Otherwise, `nil' is
 returned."
   (dbus-ignore-errors
-    ;; "Set" requires a variant.
-    (funcall
-     (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking)
-     bus service path dbus-interface-properties
-     "Set" :timeout 500 interface property (list :variant value))
-    ;; Return VALUE.
-    (dbus-get-property bus service path interface property)))
+   ;; "Set" requires a variant.
+   (dbus-call-method
+    bus service path dbus-interface-properties
+    "Set" :timeout 500 interface property (list :variant value))
+   ;; Return VALUE.
+   (dbus-get-property bus service path interface property)))
 
 (defun dbus-get-all-properties (bus service path interface)
   "Return all properties of INTERFACE at BUS, SERVICE, PATH.
@@ -884,10 +1377,7 @@
     ;; "GetAll" returns "a{sv}".
     (let (result)
       (dolist (dict
-              (funcall
-               (if noninteractive
-                   'dbus-call-method
-                 'dbus-call-method-non-blocking)
+              (dbus-call-method
                bus service path dbus-interface-properties
                "GetAll" :timeout 500 interface)
               result)
@@ -931,14 +1421,7 @@
 at a time, DONT-REGISTER-SERVICE can be used to prevent other
 clients from discovering the still incomplete interface."
   (unless (member access '(:read :readwrite))
-    (signal 'dbus-error (list "Access type invalid" access)))
-
-  ;; Register SERVICE.
-  (unless (or dont-register-service
-             (member service (dbus-list-names bus)))
-    (dbus-call-method
-     bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
-     "RequestName" service 0))
+    (signal 'wrong-type-argument (list "Access type invalid" access)))
 
   ;; Add handlers for the three property-related methods.
   (dbus-register-method
@@ -951,20 +1434,20 @@
    bus service path dbus-interface-properties "Set"
    'dbus-property-handler 'dont-register)
 
-  ;; Register the name SERVICE with BUS.
-  (unless dont-register-service
+  ;; Register SERVICE.
+  (unless (or dont-register-service (member service (dbus-list-names bus)))
     (dbus-register-service bus service))
 
   ;; Send the PropertiesChanged signal.
   (when emits-signal
     (dbus-send-signal
      bus service path dbus-interface-properties "PropertiesChanged"
-     (list (list :dict-entry property (list :variant value)))
+     `((:dict-entry ,property (:variant ,value)))
      '(:array)))
 
   ;; Create a hash table entry.  We use nil for the unique name,
   ;; because the property might be accessed from anybody.
-  (let ((key (list bus interface property))
+  (let ((key (list :property bus interface property))
        (val
         (list
          (list
@@ -979,7 +1462,7 @@
 
 (defun dbus-property-handler (&rest args)
   "Default handler for the \"org.freedesktop.DBus.Properties\" interface.
-It will be registered for all objects created by `dbus-register-object'."
+It will be registered for all objects created by `dbus-register-property'."
   (let ((bus (dbus-event-bus-name last-input-event))
        (service (dbus-event-service-name last-input-event))
        (path (dbus-event-path-name last-input-event))
@@ -989,15 +1472,15 @@
     (cond
      ;; "Get" returns a variant.
      ((string-equal method "Get")
-      (let ((entry (gethash (list bus interface property)
+      (let ((entry (gethash (list :property bus interface property)
                            dbus-registered-objects-table)))
        (when (string-equal path (nth 2 (car entry)))
-         (list (list :variant (cdar (last (car entry))))))))
+         `((:variant ,(cdar (last (car entry))))))))
 
      ;; "Set" expects a variant.
      ((string-equal method "Set")
       (let* ((value (caar (cddr args)))
-            (entry (gethash (list bus interface property)
+            (entry (gethash (list :property bus interface property)
                             dbus-registered-objects-table))
             ;; The value of the hash table is a list; in case of
             ;; properties it contains just one element (UNAME SERVICE
@@ -1012,7 +1495,7 @@
        (unless (member :readwrite (car object))
          (signal 'dbus-error
                  (list "Property not writable at path" property path)))
-       (puthash (list bus interface property)
+       (puthash (list :property bus interface property)
                 (list (append (butlast (car entry))
                               (list (cons (car object) value))))
                 dbus-registered-objects-table)
@@ -1020,7 +1503,7 @@
        (when (member :emits-signal (car object))
          (dbus-send-signal
           bus service path dbus-interface-properties "PropertiesChanged"
-          (list (list :dict-entry property (list :variant value)))
+          `((:dict-entry ,property (:variant ,value)))
           '(:array)))
        ;; Return empty reply.
        :ignore))
@@ -1030,7 +1513,7 @@
       (let (result)
        (maphash
         (lambda (key val)
-          (when (and (equal (butlast key) (list bus interface))
+          (when (and (equal (butlast key) (list :property bus interface))
                      (string-equal path (nth 2 (car val)))
                      (not (functionp (car (last (car val))))))
             (add-to-list
@@ -1042,15 +1525,151 @@
        ;; Return the result, or an empty array.
        (list :array (or result '(:signature "{sv}"))))))))
 
+
+;;; D-Bus object manager.
+
+(defun dbus-get-all-managed-objects (bus service path)
+  "Return all objects at BUS, SERVICE, PATH, and the children of PATH.
+The result is a list of objects.  Every object is a cons of an
+existing path name, and the list of available interface objects.
+An interface object is another cons, which car is the interface
+name, and the cdr is the list of properties as returned by
+`dbus-get-all-properties' for that path and interface. Example:
+
+\(dbus-get-all-managed-objects :session \"org.gnome.SettingsDaemon\" \"/\")
+
+  => \(\(\"/org/gnome/SettingsDaemon/MediaKeys\"
+       \(\"org.gnome.SettingsDaemon.MediaKeys\")
+       \(\"org.freedesktop.DBus.Peer\")
+       \(\"org.freedesktop.DBus.Introspectable\")
+       \(\"org.freedesktop.DBus.Properties\")
+       \(\"org.freedesktop.DBus.ObjectManager\"))
+      \(\"/org/gnome/SettingsDaemon/Power\"
+       \(\"org.gnome.SettingsDaemon.Power.Keyboard\")
+       \(\"org.gnome.SettingsDaemon.Power.Screen\")
+       \(\"org.gnome.SettingsDaemon.Power\"
+        \(\"Icon\" . \". GThemedIcon battery-full-charged-symbolic \")
+        \(\"Tooltip\" . \"Laptop battery is charged\"))
+       \(\"org.freedesktop.DBus.Peer\")
+       \(\"org.freedesktop.DBus.Introspectable\")
+       \(\"org.freedesktop.DBus.Properties\")
+       \(\"org.freedesktop.DBus.ObjectManager\"))
+      ...)
+
+If possible, \"org.freedesktop.DBus.ObjectManager.GetManagedObjects\"
+is used for retrieving the information.  Otherwise, the information
+is collected via \"org.freedesktop.DBus.Introspectable.Introspect\"
+and \"org.freedesktop.DBus.Properties.GetAll\", which is slow."
+    (let ((result
+          ;; Direct call.  Fails, if the target does not support the
+          ;; object manager interface.
+          (dbus-ignore-errors
+           (dbus-call-method
+            bus service path dbus-interface-objectmanager
+            "GetManagedObjects" :timeout 1000))))
+
+      (if result
+         ;; Massage the returned structure.
+         (dolist (entry result result)
+           ;; "a{oa{sa{sv}}}".
+           (dolist (entry1 (cdr entry))
+             ;; "a{sa{sv}}".
+             (dolist (entry2 entry1)
+               ;; "a{sv}".
+               (if (cadr entry2)
+                   ;; "sv".
+                   (dolist (entry3 (cadr entry2))
+                     (setcdr entry3 (caadr entry3)))
+                 (setcdr entry2 nil)))))
+
+       ;; Fallback: collect the information.  Slooow!
+       (dolist (object
+                (dbus-introspect-get-all-nodes bus service path)
+                result)
+         (let (result1)
+           (dolist
+               (interface
+                (dbus-introspect-get-interface-names bus service object)
+                result1)
+             (add-to-list
+              'result1
+              (cons interface
+                    (dbus-get-all-properties bus service object interface))))
+           (when result1
+             (add-to-list 'result (cons object result1))))))))
+
+(defun dbus-managed-objects-handler ()
+  "Default handler for the \"org.freedesktop.DBus.ObjectManager\" interface.
+It will be registered for all objects created by `dbus-register-method'."
+  (let* ((last-input-event last-input-event)
+        (bus (dbus-event-bus-name last-input-event))
+        (service (dbus-event-service-name last-input-event))
+        (path (dbus-event-path-name last-input-event)))
+    ;; "GetManagedObjects" returns "a{oa{sa{sv}}}".
+    (let (interfaces result)
+
+      ;; Check for object path wildcard interfaces.
+      (maphash
+       (lambda (key val)
+        (when (and (equal (butlast key 2) (list :method bus))
+                   (null (nth 2 (car-safe val))))
+          (add-to-list 'interfaces (nth 2 key))))
+       dbus-registered-objects-table)
+
+      ;; Check all registered object paths.
+      (maphash
+       (lambda (key val)
+        (let ((object (or (nth 2 (car-safe val)) ""))
+              (interface (nth 2 key)))
+          (when (and (equal (butlast key 2) (list :method bus))
+                     (string-prefix-p path object))
+            (dolist (interface (cons (nth 2 key) interfaces))
+              (unless (assoc object result)
+                (add-to-list 'result (list object)))
+              (unless (assoc interface (cdr (assoc object result)))
+                (setcdr
+                 (assoc object result)
+                 (append
+                  (list (cons
+                   interface
+                   ;; We simulate "org.freedesktop.DBus.Properties.GetAll"
+                   ;; by using an appropriate D-Bus event.
+                   (let ((last-input-event
+                          (append
+                           (butlast last-input-event 4)
+                           (list object dbus-interface-properties
+                                 "GetAll" 'dbus-property-handler))))
+                     (dbus-property-handler interface))))
+                  (cdr (assoc object result)))))))))
+       dbus-registered-objects-table)
+
+      ;; Return the result, or an empty array.
+      (list
+       :array
+       (or
+       (mapcar
+        (lambda (x)
+          (list
+           :dict-entry :object-path (car x)
+           (cons :array (mapcar (lambda (y) (cons :dict-entry y)) (cdr x)))))
+        result)
+       '(:signature "{oa{sa{sv}}}"))))))
+
  
-;; Initialize :system and :session buses.  This adds their file
+;; Initialize `:system' and `:session' buses.  This adds their file
 ;; descriptors to input_wait_mask, in order to detect incoming
 ;; messages immediately.
 (when (featurep 'dbusbind)
   (dbus-ignore-errors
-    (dbus-init-bus :system)
+    (dbus-init-bus :system))
+  (dbus-ignore-errors
     (dbus-init-bus :session)))
 
 (provide 'dbus)
 
+;;; TODO:
+
+;; * Implement org.freedesktop.DBus.ObjectManager.InterfacesAdded and
+;;   org.freedesktop.DBus.ObjectManager.InterfacesRemoved.
+
 ;;; dbus.el ends here

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-04-22 07:50:17 +0000
+++ b/src/ChangeLog     2012-04-22 14:11:43 +0000
@@ -1,3 +1,48 @@
+2012-04-22  Michael Albinus  <address@hidden>
+
+       Move functions from C to Lisp.  Make non-blocking method calls
+       the default.  Implement further D-Bus standard interfaces.
+
+       * dbusbind.c (DBUS_NUM_MESSAGE_TYPES): Declare.
+       (QCdbus_request_name_allow_replacement)
+       (QCdbus_request_name_replace_existing)
+       (QCdbus_request_name_do_not_queue)
+       (QCdbus_request_name_reply_primary_owner)
+       (QCdbus_request_name_reply_in_queue)
+       (QCdbus_request_name_reply_exists)
+       (QCdbus_request_name_reply_already_owner): Move to dbus.el.
+       (QCdbus_registered_serial, QCdbus_registered_method)
+       (QCdbus_registered_signal): New Lisp objects.
+       (XD_DEBUG_MESSAGE): Use sizeof.
+       (XD_MESSAGE_TYPE_TO_STRING, XD_OBJECT_TO_STRING)
+       (XD_DBUS_VALIDATE_BUS_ADDRESS, XD_DBUS_VALIDATE_OBJECT)
+       (XD_DBUS_VALIDATE_BUS_NAME, XD_DBUS_VALIDATE_PATH)
+       (XD_DBUS_VALIDATE_INTERFACE, XD_DBUS_VALIDATE_MEMBER): New macros.
+       (XD_CHECK_DBUS_SERIAL): Rename from CHECK_DBUS_SERIAL_GET_SERIAL.
+       (xd_signature, xd_append_arg): Allow float for integer types.
+       (xd_get_connection_references): New function.
+       (xd_get_connection_address): Rename from xd_initialize.  Return
+       cached address.
+       (xd_remove_watch): Do not unset $DBUS_SESSION_BUS_ADDRESS.
+       (xd_close_bus): Rename from Fdbus_close_bus.  Not needed on Lisp
+       level.
+       (Fdbus_init_bus): New optional arg PRIVATE.  Cache address.
+       Return number of recounts.
+       (Fdbus_get_unique_name): Make stronger parameter check.
+       (Fdbus_message_internal): New defun.
+       (Fdbus_call_method, Fdbus_call_method_asynchronously)
+       (Fdbus_method_return_internal, Fdbus_method_error_internal)
+       (Fdbus_send_signal, Fdbus_register_service)
+       (Fdbus_register_signal, Fdbus_register_method): Move to dbus.el.
+       (xd_read_message_1): Obey new structure of Vdbus_registered_objects.
+       (xd_read_queued_messages): Obey new structure of Vdbus_registered_buses.
+       (Vdbus_compiled_version, Vdbus_runtime_version)
+       (Vdbus_message_type_invalid, Vdbus_message_type_method_call)
+       (Vdbus_message_type_method_return, Vdbus_message_type_error)
+       (Vdbus_message_type_signal): New defvars.
+       (Vdbus_registered_buses, Vdbus_registered_objects_table): Adapt
+       docstring.
+
 2012-04-22  Paul Eggert  <address@hidden>
 
        Fix GC_MALLOC_CHECK debugging output on 64-bit hosts.

=== modified file 'src/dbusbind.c'
--- a/src/dbusbind.c    2012-02-02 12:47:09 +0000
+++ b/src/dbusbind.c    2012-04-22 14:11:43 +0000
@@ -28,19 +28,15 @@
 #include "keyboard.h"
 #include "process.h"
 
+#ifndef DBUS_NUM_MESSAGE_TYPES
+#define DBUS_NUM_MESSAGE_TYPES 5
+#endif
+
 
 /* Subroutines.  */
 static Lisp_Object Qdbus_init_bus;
-static Lisp_Object Qdbus_close_bus;
 static Lisp_Object Qdbus_get_unique_name;
-static Lisp_Object Qdbus_call_method;
-static Lisp_Object Qdbus_call_method_asynchronously;
-static Lisp_Object Qdbus_method_return_internal;
-static Lisp_Object Qdbus_method_error_internal;
-static Lisp_Object Qdbus_send_signal;
-static Lisp_Object Qdbus_register_service;
-static Lisp_Object Qdbus_register_signal;
-static Lisp_Object Qdbus_register_method;
+static Lisp_Object Qdbus_message_internal;
 
 /* D-Bus error symbol.  */
 static Lisp_Object Qdbus_error;
@@ -51,17 +47,6 @@
 /* Lisp symbol for method call timeout.  */
 static Lisp_Object QCdbus_timeout;
 
-/* Lisp symbols for name request flags.  */
-static Lisp_Object QCdbus_request_name_allow_replacement;
-static Lisp_Object QCdbus_request_name_replace_existing;
-static Lisp_Object QCdbus_request_name_do_not_queue;
-
-/* Lisp symbols for name request replies.  */
-static Lisp_Object QCdbus_request_name_reply_primary_owner;
-static Lisp_Object QCdbus_request_name_reply_in_queue;
-static Lisp_Object QCdbus_request_name_reply_exists;
-static Lisp_Object QCdbus_request_name_reply_already_owner;
-
 /* Lisp symbols of D-Bus types.  */
 static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
 static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
@@ -75,6 +60,10 @@
 static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
 static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
 
+/* Lisp symbols of objects in `dbus-registered-objects-table'.  */
+static Lisp_Object QCdbus_registered_serial, QCdbus_registered_method;
+static Lisp_Object QCdbus_registered_signal;
+
 /* Whether we are reading a D-Bus event.  */
 static int xd_in_read_queued_messages = 0;
 
@@ -120,14 +109,14 @@
   } while (0)
 
 /* Macros for debugging.  In order to enable them, build with
-   "MYCPPFLAGS='-DDBUS_DEBUG -Wall' make".  */
+   "env MYCPPFLAGS='-DDBUS_DEBUG -Wall' make".  */
 #ifdef DBUS_DEBUG
-#define XD_DEBUG_MESSAGE(...)          \
-  do {                                 \
-    char s[1024];                      \
+#define XD_DEBUG_MESSAGE(...)           \
+  do {                                  \
+    char s[1024];                       \
     snprintf (s, sizeof s, __VA_ARGS__); \
-    printf ("%s: %s\n", __func__, s);  \
-    message ("%s: %s", __func__, s);   \
+    printf ("%s: %s\n", __func__, s);   \
+    message ("%s: %s", __func__, s);    \
   } while (0)
 #define XD_DEBUG_VALID_LISP_OBJECT_P(object)                           \
   do {                                                                 \
@@ -144,7 +133,7 @@
     if (!NILP (Vdbus_debug))                                           \
       {                                                                        
\
        char s[1024];                                                   \
-       snprintf (s, 1023, __VA_ARGS__);                                \
+       snprintf (s, sizeof s, __VA_ARGS__);                            \
        message ("%s: %s", __func__, s);                                \
       }                                                                        
\
   } while (0)
@@ -241,23 +230,112 @@
 #define XD_NEXT_VALUE(object)                                          \
   ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
 
+/* Transform the message type to its string representation for debug
+   messages.  */
+#define XD_MESSAGE_TYPE_TO_STRING(mtype)                               \
+  ((mtype == DBUS_MESSAGE_TYPE_INVALID)                                        
\
+  ? "DBUS_MESSAGE_TYPE_INVALID"                                                
\
+  : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)                           \
+  ? "DBUS_MESSAGE_TYPE_METHOD_CALL"                                    \
+  : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)                         \
+  ? "DBUS_MESSAGE_TYPE_METHOD_RETURN"                                  \
+  : (mtype == DBUS_MESSAGE_TYPE_ERROR)                                 \
+   ? "DBUS_MESSAGE_TYPE_ERROR"                                         \
+   : "DBUS_MESSAGE_TYPE_SIGNAL")
+
+/* Transform the object to its string representation for debug
+   messages.  */
+#define XD_OBJECT_TO_STRING(object)                                    \
+  SDATA (format2 ("%s", object, Qnil))
+
 /* Check whether X is a valid dbus serial number.  If valid, set
    SERIAL to its value.  Otherwise, signal an error. */
-#define CHECK_DBUS_SERIAL_GET_SERIAL(x, serial)                                
\
-  do                                                                   \
-    {                                                                  \
-      dbus_uint32_t DBUS_SERIAL_MAX = -1;                              \
-      if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX)                  \
-       serial = XINT (x);                                              \
-      else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX                  \
-              && FLOATP (x)                                            \
-              && 0 <= XFLOAT_DATA (x)                                  \
-              && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX)                   \
-       serial = XFLOAT_DATA (x);                                       \
-      else                                                             \
-       XD_SIGNAL2 (build_string ("Invalid dbus serial"), x);           \
-    }                                                                  \
-  while (0)
+#define XD_CHECK_DBUS_SERIAL(x, serial)                                        
\
+  do {                                                                 \
+    dbus_uint32_t DBUS_SERIAL_MAX = -1;                                        
\
+    if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX)                    \
+      serial = XINT (x);                                               \
+    else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX                    \
+            && FLOATP (x)                                              \
+            && 0 <= XFLOAT_DATA (x)                                    \
+            && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX)                     \
+      serial = XFLOAT_DATA (x);                                                
\
+    else                                                               \
+      XD_SIGNAL2 (build_string ("Invalid dbus serial"), x);            \
+  } while (0)
+
+#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus)                              \
+  do {                                                                 \
+    if (STRINGP (bus))                                                 \
+      {                                                                        
\
+       DBusAddressEntry **entries;                                     \
+       int len;                                                        \
+       DBusError derror;                                               \
+       dbus_error_init (&derror);                                      \
+       if (!dbus_parse_address (SSDATA (bus), &entries, &len, &derror)) \
+         XD_ERROR (derror);                                            \
+       /* Cleanup.  */                                                 \
+       dbus_error_free (&derror);                                      \
+       dbus_address_entries_free (entries);                            \
+      }                                                                        
\
+                                                                       \
+    else                                                               \
+      {                                                                        
\
+       CHECK_SYMBOL (bus);                                             \
+       if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus))) \
+         XD_SIGNAL2 (build_string ("Wrong bus name"), bus);            \
+       /* We do not want to have an autolaunch for the session bus.  */ \
+       if (EQ (bus, QCdbus_session_bus)                                \
+           && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)             \
+         XD_SIGNAL2 (build_string ("No connection to bus"), bus);      \
+      }                                                                        
\
+  } while (0)
+
+#define XD_DBUS_VALIDATE_OBJECT(object, func)                          \
+  do {                                                                 \
+    if (!NILP (object))                                                        
\
+      {                                                                        
\
+       DBusError derror;                                               \
+       CHECK_STRING (object);                                          \
+       dbus_error_init (&derror);                                      \
+       if (!func (SSDATA (object), &derror))                           \
+         XD_ERROR (derror);                                            \
+       /* Cleanup.  */                                                 \
+       dbus_error_free (&derror);                                      \
+      }                                                                        
\
+  } while (0)
+
+#if HAVE_DBUS_VALIDATE_BUS_NAME
+#define XD_DBUS_VALIDATE_BUS_NAME(bus_name)                            \
+  XD_DBUS_VALIDATE_OBJECT(bus_name, dbus_validate_bus_name);
+#else
+#define XD_DBUS_VALIDATE_BUS_NAME(bus_name)                            \
+  if (!NILP (bus_name)) CHECK_STRING (bus_name);
+#endif
+
+#if HAVE_DBUS_VALIDATE_PATH
+#define XD_DBUS_VALIDATE_PATH(path)                                    \
+  XD_DBUS_VALIDATE_OBJECT(path, dbus_validate_path);
+#else
+#define XD_DBUS_VALIDATE_PATH(path)                                    \
+  if (!NILP (path)) CHECK_STRING (path);
+#endif
+
+#if HAVE_DBUS_VALIDATE_INTERFACE
+#define XD_DBUS_VALIDATE_INTERFACE(interface)                          \
+  XD_DBUS_VALIDATE_OBJECT(interface, dbus_validate_interface);
+#else
+#define XD_DBUS_VALIDATE_INTERFACE(interface)                          \
+  if (!NILP (interface)) CHECK_STRING (interface);
+#endif
+
+#if HAVE_DBUS_VALIDATE_MEMBER
+#define XD_DBUS_VALIDATE_MEMBER(member)                                        
\
+  XD_DBUS_VALIDATE_OBJECT(member, dbus_validate_member);
+#else
+#define XD_DBUS_VALIDATE_MEMBER(member)                                        
\
+  if (!NILP (member)) CHECK_STRING (member);
+#endif
 
 /* Append to SIGNATURE a copy of X, making sure SIGNATURE does
    not become too long.  */
@@ -293,11 +371,6 @@
     {
     case DBUS_TYPE_BYTE:
     case DBUS_TYPE_UINT16:
-    case DBUS_TYPE_UINT32:
-    case DBUS_TYPE_UINT64:
-#ifdef DBUS_TYPE_UNIX_FD
-    case DBUS_TYPE_UNIX_FD:
-#endif
       CHECK_NATNUM (object);
       sprintf (signature, "%c", dtype);
       break;
@@ -309,14 +382,19 @@
       break;
 
     case DBUS_TYPE_INT16:
-    case DBUS_TYPE_INT32:
-    case DBUS_TYPE_INT64:
       CHECK_NUMBER (object);
       sprintf (signature, "%c", dtype);
       break;
 
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UINT64:
+#ifdef DBUS_TYPE_UNIX_FD
+    case DBUS_TYPE_UNIX_FD:
+#endif
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_INT64:
     case DBUS_TYPE_DOUBLE:
-      CHECK_FLOAT (object);
+      CHECK_NUMBER_OR_FLOAT (object);
       sprintf (signature, "%c", dtype);
       break;
 
@@ -352,8 +430,8 @@
        }
 
       /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
-        only element, the value of this element is used as he array's
-        element signature.  */
+        only element, the value of this element is used as the
+        array's element signature.  */
       if ((subtype == DBUS_TYPE_SIGNATURE)
          && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
          && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
@@ -505,9 +583,8 @@
        }
 
       case DBUS_TYPE_INT32:
-       CHECK_NUMBER (object);
        {
-         dbus_int32_t val = XINT (object);
+         dbus_int32_t val = extract_float (object);
          XD_DEBUG_MESSAGE ("%c %d", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
            XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -518,9 +595,8 @@
 #ifdef DBUS_TYPE_UNIX_FD
       case DBUS_TYPE_UNIX_FD:
 #endif
-       CHECK_NATNUM (object);
        {
-         dbus_uint32_t val = XFASTINT (object);
+         dbus_uint32_t val = extract_float (object);
          XD_DEBUG_MESSAGE ("%c %u", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
            XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -528,9 +604,8 @@
        }
 
       case DBUS_TYPE_INT64:
-       CHECK_NUMBER (object);
        {
-         dbus_int64_t val = XINT (object);
+         dbus_int64_t val = extract_float (object);
          XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
            XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -538,19 +613,17 @@
        }
 
       case DBUS_TYPE_UINT64:
-       CHECK_NATNUM (object);
        {
-         dbus_uint64_t val = XFASTINT (object);
-         XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, XFASTINT (object));
+         dbus_uint64_t val = extract_float (object);
+         XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
            XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
       case DBUS_TYPE_DOUBLE:
-       CHECK_FLOAT (object);
        {
-         double val = XFLOAT_DATA (object);
+         double val = extract_float (object);
          XD_DEBUG_MESSAGE ("%c %f", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
            XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -614,7 +687,7 @@
                            dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
 
          XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
-                           SDATA (format2 ("%s", object, Qnil)));
+                           XD_OBJECT_TO_STRING (object));
          if (!dbus_message_iter_open_container (iter, dtype,
                                                 signature, &subiter))
            XD_SIGNAL3 (build_string ("Cannot open container"),
@@ -627,7 +700,7 @@
                        dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
 
          XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
-                           SDATA (format2 ("%s", object, Qnil)));
+                           XD_OBJECT_TO_STRING (object));
          if (!dbus_message_iter_open_container (iter, dtype,
                                                 signature, &subiter))
            XD_SIGNAL3 (build_string ("Cannot open container"),
@@ -637,8 +710,7 @@
        case DBUS_TYPE_STRUCT:
        case DBUS_TYPE_DICT_ENTRY:
          /* These containers do not require a signature.  */
-         XD_DEBUG_MESSAGE ("%c %s", dtype,
-                           SDATA (format2 ("%s", object, Qnil)));
+         XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (object));
          if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
            XD_SIGNAL2 (build_string ("Cannot open container"),
                        make_number (dtype));
@@ -777,7 +849,7 @@
            result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
            dbus_message_iter_next (&subiter);
          }
-       XD_DEBUG_MESSAGE ("%c %s", dtype, SDATA (format2 ("%s", result, Qnil)));
+       XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (result));
        RETURN_UNGCPRO (Fnreverse (result));
       }
 
@@ -787,85 +859,37 @@
     }
 }
 
-/* Initialize D-Bus connection.  BUS is either a Lisp symbol, :system
-   or :session, or a string denoting the bus address.  It tells which
-   D-Bus to initialize.  If RAISE_ERROR is non-zero, signal an error
-   when the connection cannot be initialized.  */
+/* Return the number of references of the shared CONNECTION.  */
+static int
+xd_get_connection_references (DBusConnection *connection)
+{
+  ptrdiff_t *refcount;
+  
+  /* We cannot access the DBusConnection structure, it is not public.
+     But we know, that the reference counter is the first field in
+     that structure.  */
+  refcount = (void *) &connection;
+  refcount =  (void *) *refcount;
+  return *refcount;
+}
+
+/* Return D-Bus connection address.  BUS is either a Lisp symbol,
+   :system or :session, or a string denoting the bus address.  */
 static DBusConnection *
-xd_initialize (Lisp_Object bus, int raise_error)
+xd_get_connection_address (Lisp_Object bus)
 {
   DBusConnection *connection;
-  DBusError derror;
-
-  /* Parameter check.  */
-  if (!STRINGP (bus))
-    {
-      CHECK_SYMBOL (bus);
-      if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus)))
-       {
-         if (raise_error)
-           XD_SIGNAL2 (build_string ("Wrong bus name"), bus);
-         else
-           return NULL;
-       }
-
-      /* We do not want to have an autolaunch for the session bus.  */
-      if (EQ (bus, QCdbus_session_bus)
-         && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
-       {
-         if (raise_error)
-           XD_SIGNAL2 (build_string ("No connection to bus"), bus);
-         else
-           return NULL;
-       }
-    }
-
-  /* Open a connection to the bus.  */
-  dbus_error_init (&derror);
-
-  if (STRINGP (bus))
-      connection = dbus_connection_open (SSDATA (bus), &derror);
+  Lisp_Object val;
+
+  val = CDR_SAFE (Fassoc (bus, Vdbus_registered_buses));
+  if (NILP (val))
+    XD_SIGNAL2 (build_string ("No connection to bus"), bus);
   else
-    if (EQ (bus, QCdbus_system_bus))
-      connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
-    else
-      connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
-
-  if (dbus_error_is_set (&derror))
-    {
-      if (raise_error)
-       XD_ERROR (derror);
-      else
-       connection = NULL;
-    }
-
-  /* If it is not the system or session bus, we must register
-     ourselves.  Otherwise, we have called dbus_bus_get, which has
-     configured us to exit if the connection closes - we undo this
-     setting.  */
-  if (connection != NULL)
-    {
-      if (STRINGP (bus))
-       dbus_bus_register (connection, &derror);
-      else
-       dbus_connection_set_exit_on_disconnect (connection, FALSE);
-    }
-
-  if (dbus_error_is_set (&derror))
-    {
-      if (raise_error)
-       XD_ERROR (derror);
-      else
-       connection = NULL;
-    }
-
-  if (connection == NULL && raise_error)
+    connection = (DBusConnection *) XFASTINT (val);
+
+  if (!dbus_connection_get_is_connected (connection))
     XD_SIGNAL2 (build_string ("No connection to bus"), bus);
 
-  /* Cleanup.  */
-  dbus_error_free (&derror);
-
-  /* Return the result.  */
   return connection;
 }
 
@@ -896,8 +920,8 @@
   int fd = xd_find_watch_fd (watch);
 
   XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
-                    fd, flags & DBUS_WATCH_WRITABLE,
-                    dbus_watch_get_enabled (watch));
+                   fd, flags & DBUS_WATCH_WRITABLE,
+                   dbus_watch_get_enabled (watch));
 
   if (fd == -1)
     return FALSE;
@@ -929,8 +953,8 @@
   /* Unset session environment.  */
   if (XSYMBOL (QCdbus_session_bus) == data)
     {
-      XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
-      unsetenv ("DBUS_SESSION_BUS_ADDRESS");
+      //      XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
+      //      unsetenv ("DBUS_SESSION_BUS_ADDRESS");
     }
 
   if (flags & DBUS_WATCH_WRITABLE)
@@ -949,23 +973,111 @@
     xd_remove_watch (watch, data);
 }
 
-DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
-       doc: /* Initialize connection to D-Bus BUS.  */)
-  (Lisp_Object bus)
-{
-  DBusConnection *connection;
-  void *busp;
+/* Close connection to D-Bus BUS.  */
+static void
+xd_close_bus (Lisp_Object bus)
+{
+  DBusConnection *connection;
+  Lisp_Object val;
+
+  /* Check whether we are connected.  */
+  val = Fassoc (bus, Vdbus_registered_buses);
+  if (NILP (val))
+    return;
+
+  /* Retrieve bus address.  */
+  connection = xd_get_connection_address (bus);
+
+  /* Close connection, if there isn't another shared application.  */
+  if (xd_get_connection_references (connection) == 1)
+    {
+      XD_DEBUG_MESSAGE ("Close connection to bus %s",
+                       XD_OBJECT_TO_STRING (bus));
+      dbus_connection_close (connection);
+    }
+
+  /* Decrement reference count.  */
+  dbus_connection_unref (connection);
+
+  /* Remove bus from list of registered buses.  */
+  Vdbus_registered_buses = Fdelete (val, Vdbus_registered_buses);
+
+  /* Return.  */
+  return;
+}
+
+DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 2, 0,
+       doc: /* Establish the connection to D-Bus BUS.
+
+BUS can be either the symbol `:system' or the symbol `:session', or it
+can be a string denoting the address of the corresponding bus.  For
+the system and session buses, this function is called when loading
+`dbus.el', there is no need to call it again.
+
+The function returns a number, which counts the connections this Emacs
+session has established to the BUS under the same unique name (see
+`dbus-get-unique-name').  It depends on the libraries Emacs is linked
+with, and on the environment Emacs is running.  For example, if Emacs
+is linked with the gtk toolkit, and it runs in a GTK-aware environment
+like Gnome, another connection might already be established.
+
+When PRIVATE is non-nil, a new connection is established instead of
+reusing an existing one.  It results in a new unique name at the bus.
+This can be used, if it is necessary to distinguish from another
+connection used in the same Emacs process, like the one established by
+GTK+.  It should be used with care for at least the `:system' and
+`:session' buses, because other Emacs Lisp packages might already use
+this connection to those buses.  */)
+  (Lisp_Object bus, Lisp_Object private)
+{
+  DBusConnection *connection;
+  DBusError derror;
+  Lisp_Object val;
+  int refcount;
 
   /* Check parameter.  */
-  if (SYMBOLP (bus))
-    busp = XSYMBOL (bus);
-  else if (STRINGP (bus))
-    busp = XSTRING (bus);
-  else
-    wrong_type_argument (intern ("D-Bus"), bus);
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
+  XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
+
+  /* Close bus if it is already open.  */
+  xd_close_bus (bus);
+
+  /* Initialize.  */
+  dbus_error_init (&derror);
+
+  /* Open the connection.  */
+  if (STRINGP (bus))
+    if (NILP (private))
+      connection = dbus_connection_open (SSDATA (bus), &derror);
+    else
+      connection = dbus_connection_open_private (SSDATA (bus), &derror);
+
+  else
+    if (NILP (private))
+      connection = dbus_bus_get (EQ (bus, QCdbus_system_bus)
+                                ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
+                                &derror);
+    else
+      connection = dbus_bus_get_private (EQ (bus, QCdbus_system_bus)
+                                        ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
+                                        &derror);
+
+  if (dbus_error_is_set (&derror))
+    XD_ERROR (derror);
+
+  if (connection == NULL)
+    XD_SIGNAL2 (build_string ("No connection to bus"), bus);
+
+  /* If it is not the system or session bus, we must register
+     ourselves.  Otherwise, we have called dbus_bus_get, which has
+     configured us to exit if the connection closes - we undo this
+     setting.  */
+  if (STRINGP (bus))
+    dbus_bus_register (connection, &derror);
+  else
+    dbus_connection_set_exit_on_disconnect (connection, FALSE);
+
+  if (dbus_error_is_set (&derror))
+    XD_ERROR (derror);
 
   /* Add the watch functions.  We pass also the bus as data, in order
      to distinguish between the buses in xd_remove_watch.  */
@@ -973,36 +1085,27 @@
                                            xd_add_watch,
                                            xd_remove_watch,
                                             xd_toggle_watch,
-                                           busp, NULL))
+                                           SYMBOLP (bus)
+                                           ? (void *) XSYMBOL (bus)
+                                           : (void *) XSTRING (bus),
+                                           NULL))
     XD_SIGNAL1 (build_string ("Cannot add watch functions"));
 
   /* Add bus to list of registered buses.  */
-  Vdbus_registered_buses =  Fcons (bus, Vdbus_registered_buses);
+  XSETFASTINT (val, connection);
+  Vdbus_registered_buses = Fcons (Fcons (bus, val), Vdbus_registered_buses);
 
   /* We do not want to abort.  */
   putenv ((char *) "DBUS_FATAL_WARNINGS=0");
 
-  /* Return.  */
-  return Qnil;
-}
-
-DEFUN ("dbus-close-bus", Fdbus_close_bus, Sdbus_close_bus, 1, 1, 0,
-       doc: /* Close connection to D-Bus BUS.  */)
-  (Lisp_Object bus)
-{
-  DBusConnection *connection;
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Decrement reference count to the bus.  */
-  dbus_connection_unref (connection);
-
-  /* Remove bus from list of registered buses.  */
-  Vdbus_registered_buses = Fdelete (bus, Vdbus_registered_buses);
-
-  /* Return.  */
-  return Qnil;
+  /* Cleanup.  */
+  dbus_error_free (&derror);
+
+  /* Return reference counter.  */
+  refcount = xd_get_connection_references (connection);
+  XD_DEBUG_MESSAGE ("Bus %s, Reference counter %d",
+                   XD_OBJECT_TO_STRING (bus), refcount);
+  return make_number (refcount);
 }
 
 DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
@@ -1013,8 +1116,11 @@
   DBusConnection *connection;
   const char *name;
 
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
+  /* Check parameter.  */
+  XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
+
+  /* Retrieve bus address.  */
+  connection = xd_get_connection_address (bus);
 
   /* Request the name.  */
   name = dbus_bus_get_unique_name (connection);
@@ -1025,341 +1131,241 @@
   return build_string (name);
 }
 
-DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
-       doc: /* Call METHOD on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name to be used.  PATH is the D-Bus
-object path SERVICE is registered at.  INTERFACE is an interface
-offered by SERVICE.  It must provide METHOD.
-
-If the parameter `:timeout' is given, the following integer TIMEOUT
-specifies the maximum number of milliseconds the method call must
-return.  The default value is 25,000.  If the method call doesn't
-return in time, a D-Bus error is raised.
-
-All other arguments ARGS are passed to METHOD as arguments.  They are
-converted into D-Bus types via the following rules:
-
-  t and nil => DBUS_TYPE_BOOLEAN
-  number    => DBUS_TYPE_UINT32
-  integer   => DBUS_TYPE_INT32
-  float     => DBUS_TYPE_DOUBLE
-  string    => DBUS_TYPE_STRING
-  list      => DBUS_TYPE_ARRAY
-
-All arguments can be preceded by a type symbol.  For details about
-type symbols, see Info node `(dbus)Type Conversion'.
-
-`dbus-call-method' returns the resulting values of METHOD as a list of
-Lisp objects.  The type conversion happens the other direction as for
-input arguments.  It follows the mapping rules:
-
-  DBUS_TYPE_BOOLEAN     => t or nil
-  DBUS_TYPE_BYTE        => number
-  DBUS_TYPE_UINT16      => number
-  DBUS_TYPE_INT16       => integer
-  DBUS_TYPE_UINT32      => number or float
-  DBUS_TYPE_UNIX_FD     => number or float
-  DBUS_TYPE_INT32       => integer or float
-  DBUS_TYPE_UINT64      => number or float
-  DBUS_TYPE_INT64       => integer or float
-  DBUS_TYPE_DOUBLE      => float
-  DBUS_TYPE_STRING      => string
-  DBUS_TYPE_OBJECT_PATH => string
-  DBUS_TYPE_SIGNATURE   => string
-  DBUS_TYPE_ARRAY       => list
-  DBUS_TYPE_VARIANT     => list
-  DBUS_TYPE_STRUCT      => list
-  DBUS_TYPE_DICT_ENTRY  => list
-
-Example:
-
-\(dbus-call-method
-  :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
-  "org.gnome.seahorse.Keys" "GetKeyField"
-  "openpgp:657984B8C7A966DD" "simple-name")
-
-  => (t ("Philip R. Zimmermann"))
-
-If the result of the METHOD call is just one value, the converted Lisp
-object is returned instead of a list containing this single Lisp object.
-
-\(dbus-call-method
-  :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
-  "org.freedesktop.Hal.Device" "GetPropertyString"
-  "system.kernel.machine")
-
-  => "i686"
-
-usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout 
TIMEOUT &rest ARGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service, path, interface, method;
-  Lisp_Object result;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-  DBusConnection *connection;
-  DBusMessage *dmessage;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  unsigned int dtype;
-  int timeout = -1;
-  ptrdiff_t i = 5;
-  char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
-
-  /* Check parameters.  */
-  bus = args[0];
-  service = args[1];
-  path = args[2];
-  interface = args[3];
-  method = args[4];
-
-  CHECK_STRING (service);
-  CHECK_STRING (path);
-  CHECK_STRING (interface);
-  CHECK_STRING (method);
-  GCPRO5 (bus, service, path, interface, method);
-
-  XD_DEBUG_MESSAGE ("%s %s %s %s",
-                   SDATA (service),
-                   SDATA (path),
-                   SDATA (interface),
-                   SDATA (method));
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Create the message.  */
-  dmessage = dbus_message_new_method_call (SSDATA (service),
-                                          SSDATA (path),
-                                          SSDATA (interface),
-                                          SSDATA (method));
-  UNGCPRO;
-  if (dmessage == NULL)
-    XD_SIGNAL1 (build_string ("Unable to create a new message"));
-
-  /* Check for timeout parameter.  */
-  if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
-    {
-      CHECK_NATNUM (args[i+1]);
-      timeout = XFASTINT (args[i+1]);
-      i = i+2;
-    }
-
-  /* Initialize parameter list of message.  */
-  dbus_message_iter_init_append (dmessage, &iter);
-
-  /* Append parameters to the message.  */
-  for (; i < nargs; ++i)
-    {
-      dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
-      if (XD_DBUS_TYPE_P (args[i]))
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)),
-                           SDATA (format2 ("%s", args[i+1], Qnil)));
-         ++i;
-       }
-      else
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)));
-       }
-
-      /* Check for valid signature.  We use DBUS_TYPE_INVALID as
-        indication that there is no parent type.  */
-      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
-
-      xd_append_arg (dtype, args[i], &iter);
-    }
-
-  /* Send the message.  */
-  dbus_error_init (&derror);
-  reply = dbus_connection_send_with_reply_and_block (connection,
-                                                    dmessage,
-                                                    timeout,
-                                                    &derror);
-
-  if (dbus_error_is_set (&derror))
-    XD_ERROR (derror);
-
-  if (reply == NULL)
-    XD_SIGNAL1 (build_string ("No reply"));
-
-  XD_DEBUG_MESSAGE ("Message sent");
-
-  /* Collect the results.  */
-  result = Qnil;
-  GCPRO1 (result);
-
-  if (dbus_message_iter_init (reply, &iter))
-    {
-      /* Loop over the parameters of the D-Bus reply message.  Construct a
-        Lisp list, which is returned by `dbus-call-method'.  */
-      while ((dtype = dbus_message_iter_get_arg_type (&iter))
-            != DBUS_TYPE_INVALID)
-       {
-         result = Fcons (xd_retrieve_arg (dtype, &iter), result);
-         dbus_message_iter_next (&iter);
-       }
-    }
-  else
-    {
-      /* No arguments: just return nil.  */
-    }
-
-  /* Cleanup.  */
-  dbus_error_free (&derror);
-  dbus_message_unref (dmessage);
-  dbus_message_unref (reply);
-
-  /* Return the result.  If there is only one single Lisp object,
-     return it as-it-is, otherwise return the reversed list.  */
-  if (XFASTINT (Flength (result)) == 1)
-    RETURN_UNGCPRO (CAR_SAFE (result));
-  else
-    RETURN_UNGCPRO (Fnreverse (result));
-}
-
-DEFUN ("dbus-call-method-asynchronously", Fdbus_call_method_asynchronously,
-       Sdbus_call_method_asynchronously, 6, MANY, 0,
-       doc: /* Call METHOD on the D-Bus BUS asynchronously.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name to be used.  PATH is the D-Bus
-object path SERVICE is registered at.  INTERFACE is an interface
-offered by SERVICE.  It must provide METHOD.
-
-HANDLER is a Lisp function, which is called when the corresponding
-return message has arrived.  If HANDLER is nil, no return message will
-be expected.
-
-If the parameter `:timeout' is given, the following integer TIMEOUT
-specifies the maximum number of milliseconds the method call must
-return.  The default value is 25,000.  If the method call doesn't
-return in time, a D-Bus error is raised.
-
-All other arguments ARGS are passed to METHOD as arguments.  They are
-converted into D-Bus types via the following rules:
-
-  t and nil => DBUS_TYPE_BOOLEAN
-  number    => DBUS_TYPE_UINT32
-  integer   => DBUS_TYPE_INT32
-  float     => DBUS_TYPE_DOUBLE
-  string    => DBUS_TYPE_STRING
-  list      => DBUS_TYPE_ARRAY
-
-All arguments can be preceded by a type symbol.  For details about
-type symbols, see Info node `(dbus)Type Conversion'.
-
-Unless HANDLER is nil, the function returns a key into the hash table
-`dbus-registered-objects-table'.  The corresponding entry in the hash
-table is removed, when the return message has been arrived, and
-HANDLER is called.
-
-Example:
-
-\(dbus-call-method-asynchronously
-  :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
-  "org.freedesktop.Hal.Device" "GetPropertyString" 'message
-  "system.kernel.machine")
-
-  => (:system 2)
-
-  -| i686
-
-usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD 
HANDLER &optional :timeout TIMEOUT &rest ARGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service, path, interface, method, handler;
+DEFUN ("dbus-message-internal", Fdbus_message_internal, Sdbus_message_internal,
+       4, MANY, 0,
+       doc: /* Send a D-Bus message.
+This is an internal function, it shall not be used outside dbus.el.
+
+The following usages are expected:
+
+`dbus-call-method', `dbus-call-method-asynchronously':
+  \(dbus-message-internal
+    dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER
+    &optional :timeout TIMEOUT &rest ARGS)
+
+`dbus-send-signal':
+  \(dbus-message-internal
+    dbus-message-type-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)
+
+`dbus-method-return-internal':
+  \(dbus-message-internal
+    dbus-message-type-method-return BUS SERVICE SERIAL &rest ARGS)
+
+`dbus-method-error-internal':
+  \(dbus-message-internal
+    dbus-message-type-error BUS SERVICE SERIAL &rest ARGS)
+
+usage: (dbus-message-internal &rest REST)  */)
+  (ptrdiff_t nargs, Lisp_Object *args)
+{
+  Lisp_Object message_type, bus, service, handler;
+  Lisp_Object path = Qnil;
+  Lisp_Object interface = Qnil;
+  Lisp_Object member = Qnil;
   Lisp_Object result;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   DBusConnection *connection;
   DBusMessage *dmessage;
   DBusMessageIter iter;
   unsigned int dtype;
-  dbus_uint32_t serial;
+  unsigned int mtype;
+  dbus_uint32_t serial = 0;
   int timeout = -1;
-  ptrdiff_t i = 6;
+  ptrdiff_t count;
   char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
 
+  /* Initialize parameters.  */
+  message_type = args[0];
+  bus = args[1];
+  service = args[2];
+  handler = Qnil;
+
+  CHECK_NATNUM (message_type);
+  mtype = XFASTINT (message_type);
+  if ((mtype <= DBUS_MESSAGE_TYPE_INVALID) || (mtype >= 
DBUS_NUM_MESSAGE_TYPES))
+    XD_SIGNAL2 (build_string ("Invalid message type"), message_type);
+
+  if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
+      || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
+    {
+      path = args[3];
+      interface = args[4];
+      member = args[5];
+      if (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
+       handler = args[6];
+      count = (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) ? 7 : 6;
+    }
+  else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR  */
+    {
+      XD_CHECK_DBUS_SERIAL (args[3], serial);
+      count = 4;
+    }
+
   /* Check parameters.  */
-  bus = args[0];
-  service = args[1];
-  path = args[2];
-  interface = args[3];
-  method = args[4];
-  handler = args[5];
-
-  CHECK_STRING (service);
-  CHECK_STRING (path);
-  CHECK_STRING (interface);
-  CHECK_STRING (method);
-  if (!NILP (handler) && !FUNCTIONP (handler))
-    wrong_type_argument (Qinvalid_function, handler);
-  GCPRO6 (bus, service, path, interface, method, handler);
-
-  XD_DEBUG_MESSAGE ("%s %s %s %s",
-                   SDATA (service),
-                   SDATA (path),
-                   SDATA (interface),
-                   SDATA (method));
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Create the message.  */
-  dmessage = dbus_message_new_method_call (SSDATA (service),
-                                          SSDATA (path),
-                                          SSDATA (interface),
-                                          SSDATA (method));
+  XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
+  XD_DBUS_VALIDATE_BUS_NAME (service);
+  if (nargs < count)
+    xsignal2 (Qwrong_number_of_arguments,
+             Qdbus_message_internal,
+             make_number (nargs));
+
+  if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
+      || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
+    {
+      XD_DBUS_VALIDATE_PATH (path);
+      XD_DBUS_VALIDATE_INTERFACE (interface);
+      XD_DBUS_VALIDATE_MEMBER (member);
+      if (!NILP (handler) && (!FUNCTIONP (handler)))
+       wrong_type_argument (Qinvalid_function, handler);
+    }
+
+  /* Protect Lisp variables.  */
+  GCPRO6 (bus, service, path, interface, member, handler);
+
+  /* Trace parameters.  */
+  switch (mtype)
+    {
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      XD_DEBUG_MESSAGE ("%s %s %s %s %s %s %s",
+                       XD_MESSAGE_TYPE_TO_STRING (mtype),
+                       XD_OBJECT_TO_STRING (bus),
+                       XD_OBJECT_TO_STRING (service),
+                       XD_OBJECT_TO_STRING (path),
+                       XD_OBJECT_TO_STRING (interface),
+                       XD_OBJECT_TO_STRING (member),
+                       XD_OBJECT_TO_STRING (handler));
+      break;
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+      XD_DEBUG_MESSAGE ("%s %s %s %s %s %s",
+                       XD_MESSAGE_TYPE_TO_STRING (mtype),
+                       XD_OBJECT_TO_STRING (bus),
+                       XD_OBJECT_TO_STRING (service),
+                       XD_OBJECT_TO_STRING (path),
+                       XD_OBJECT_TO_STRING (interface),
+                       XD_OBJECT_TO_STRING (member));
+      break;
+    default: /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR  */
+      XD_DEBUG_MESSAGE ("%s %s %s %u",
+                       XD_MESSAGE_TYPE_TO_STRING (mtype),
+                       XD_OBJECT_TO_STRING (bus),
+                       XD_OBJECT_TO_STRING (service),
+                       serial);
+    }
+
+  /* Retrieve bus address.  */
+  connection = xd_get_connection_address (bus);
+
+  /* Create the D-Bus message.  */
+  dmessage = dbus_message_new (mtype);
   if (dmessage == NULL)
-    XD_SIGNAL1 (build_string ("Unable to create a new message"));
+    {
+      UNGCPRO;
+      XD_SIGNAL1 (build_string ("Unable to create a new message"));
+    }
+
+  if (STRINGP (service))
+    {
+      if (mtype != DBUS_MESSAGE_TYPE_SIGNAL)
+       /* Set destination.  */
+       {
+         if (!dbus_message_set_destination (dmessage, SSDATA (service)))
+           {
+             UNGCPRO;
+             XD_SIGNAL2 (build_string ("Unable to set the destination"),
+                         service);
+           }
+       }
+
+      else
+       /* Set destination for unicast signals.  */
+       {
+         Lisp_Object uname;
+
+         /* If it is the same unique name as we are registered at the
+            bus or an unknown name, we regard it as broadcast message
+            due to backward compatibility.  */
+         if (dbus_bus_name_has_owner (connection, SSDATA (service), NULL))
+           uname = call2 (intern ("dbus-get-name-owner"), bus, service);
+         else
+           uname = Qnil;
+
+         if (STRINGP (uname)
+             && (strcmp (dbus_bus_get_unique_name (connection), SSDATA (uname))
+                 != 0)
+             && (!dbus_message_set_destination (dmessage, SSDATA (service))))
+           {
+             UNGCPRO;
+             XD_SIGNAL2 (build_string ("Unable to set signal destination"),
+                         service);
+           }
+       }
+    }
+
+  /* Set message parameters.  */
+  if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
+      || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
+    {
+      if ((!dbus_message_set_path (dmessage, SSDATA (path)))
+         || (!dbus_message_set_interface (dmessage, SSDATA (interface)))
+         || (!dbus_message_set_member (dmessage, SSDATA (member))))
+       {
+         UNGCPRO;
+         XD_SIGNAL1 (build_string ("Unable to set the message parameter"));
+       }
+    }
+
+  else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR  */
+    {
+      if (!dbus_message_set_reply_serial (dmessage, serial))
+       {
+         UNGCPRO;
+         XD_SIGNAL1 (build_string ("Unable to create a return message"));
+       }
+
+      if ((mtype == DBUS_MESSAGE_TYPE_ERROR)
+         && (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED)))
+       {
+         UNGCPRO;
+         XD_SIGNAL1 (build_string ("Unable to create a error message"));
+       }
+    }
 
   /* Check for timeout parameter.  */
-  if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
+  if ((count+2 <= nargs) && (EQ ((args[count]), QCdbus_timeout)))
     {
-      CHECK_NATNUM (args[i+1]);
-      timeout = XFASTINT (args[i+1]);
-      i = i+2;
+      CHECK_NATNUM (args[count+1]);
+      timeout = XFASTINT (args[count+1]);
+      count = count+2;
     }
 
   /* Initialize parameter list of message.  */
   dbus_message_iter_init_append (dmessage, &iter);
 
   /* Append parameters to the message.  */
-  for (; i < nargs; ++i)
+  for (; count < nargs; ++count)
     {
-      dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
-      if (XD_DBUS_TYPE_P (args[i]))
+      dtype = XD_OBJECT_TO_DBUS_TYPE (args[count]);
+      if (XD_DBUS_TYPE_P (args[count]))
        {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)),
-                           SDATA (format2 ("%s", args[i+1], Qnil)));
-         ++i;
+         XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
+         XD_DEBUG_VALID_LISP_OBJECT_P (args[count+1]);
+         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", count - 4,
+                           XD_OBJECT_TO_STRING (args[count]),
+                           XD_OBJECT_TO_STRING (args[count+1]));
+         ++count;
        }
       else
        {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)));
+         XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
+         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", count - 4,
+                           XD_OBJECT_TO_STRING (args[count]));
        }
 
       /* Check for valid signature.  We use DBUS_TYPE_INVALID as
         indication that there is no parent type.  */
-      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
+      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[count]);
 
-      xd_append_arg (dtype, args[i], &iter);
+      xd_append_arg (dtype, args[count], &iter);
     }
 
   if (!NILP (handler))
@@ -1368,11 +1374,15 @@
         message queue.  */
       if (!dbus_connection_send_with_reply (connection, dmessage,
                                            NULL, timeout))
-       XD_SIGNAL1 (build_string ("Cannot send message"));
+       {
+         UNGCPRO;
+         XD_SIGNAL1 (build_string ("Cannot send message"));
+       }
 
       /* The result is the key in Vdbus_registered_objects_table.  */
       serial = dbus_message_get_serial (dmessage);
-      result = list2 (bus, make_fixnum_or_float (serial));
+      result = list3 (QCdbus_registered_serial,
+                     bus, make_fixnum_or_float (serial));
 
       /* Create a hash table entry.  */
       Fputhash (result, handler, Vdbus_registered_objects_table);
@@ -1382,12 +1392,15 @@
       /* Send the message.  The message is just added to the outgoing
         message queue.  */
       if (!dbus_connection_send (connection, dmessage, NULL))
-       XD_SIGNAL1 (build_string ("Cannot send message"));
+       {
+         UNGCPRO;
+         XD_SIGNAL1 (build_string ("Cannot send message"));
+       }
 
       result = Qnil;
     }
 
-  XD_DEBUG_MESSAGE ("Message sent");
+  XD_DEBUG_MESSAGE ("Message sent: %s", XD_OBJECT_TO_STRING (result));
 
   /* Cleanup.  */
   dbus_message_unref (dmessage);
@@ -1396,300 +1409,6 @@
   RETURN_UNGCPRO (result);
 }
 
-DEFUN ("dbus-method-return-internal", Fdbus_method_return_internal,
-       Sdbus_method_return_internal,
-       3, MANY, 0,
-       doc: /* Return for message SERIAL on the D-Bus BUS.
-This is an internal function, it shall not be used outside dbus.el.
-
-usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service;
-  struct gcpro gcpro1, gcpro2;
-  DBusConnection *connection;
-  DBusMessage *dmessage;
-  DBusMessageIter iter;
-  dbus_uint32_t serial;
-  unsigned int ui_serial, dtype;
-  ptrdiff_t i;
-  char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
-
-  /* Check parameters.  */
-  bus = args[0];
-  service = args[2];
-
-  CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
-  CHECK_STRING (service);
-  GCPRO2 (bus, service);
-
-  ui_serial = serial;
-  XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Create the message.  */
-  dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
-  if ((dmessage == NULL)
-      || (!dbus_message_set_reply_serial (dmessage, serial))
-      || (!dbus_message_set_destination (dmessage, SSDATA (service))))
-    {
-      UNGCPRO;
-      XD_SIGNAL1 (build_string ("Unable to create a return message"));
-    }
-
-  UNGCPRO;
-
-  /* Initialize parameter list of message.  */
-  dbus_message_iter_init_append (dmessage, &iter);
-
-  /* Append parameters to the message.  */
-  for (i = 3; i < nargs; ++i)
-    {
-      dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
-      if (XD_DBUS_TYPE_P (args[i]))
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 2,
-                           SDATA (format2 ("%s", args[i], Qnil)),
-                           SDATA (format2 ("%s", args[i+1], Qnil)));
-         ++i;
-       }
-      else
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 2,
-                           SDATA (format2 ("%s", args[i], Qnil)));
-       }
-
-      /* Check for valid signature.  We use DBUS_TYPE_INVALID as
-        indication that there is no parent type.  */
-      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
-
-      xd_append_arg (dtype, args[i], &iter);
-    }
-
-  /* Send the message.  The message is just added to the outgoing
-     message queue.  */
-  if (!dbus_connection_send (connection, dmessage, NULL))
-    XD_SIGNAL1 (build_string ("Cannot send message"));
-
-  XD_DEBUG_MESSAGE ("Message sent");
-
-  /* Cleanup.  */
-  dbus_message_unref (dmessage);
-
-  /* Return.  */
-  return Qt;
-}
-
-DEFUN ("dbus-method-error-internal", Fdbus_method_error_internal,
-       Sdbus_method_error_internal,
-       3, MANY, 0,
-       doc: /* Return error message for message SERIAL on the D-Bus BUS.
-This is an internal function, it shall not be used outside dbus.el.
-
-usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service;
-  struct gcpro gcpro1, gcpro2;
-  DBusConnection *connection;
-  DBusMessage *dmessage;
-  DBusMessageIter iter;
-  dbus_uint32_t serial;
-  unsigned int ui_serial, dtype;
-  ptrdiff_t i;
-  char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
-
-  /* Check parameters.  */
-  bus = args[0];
-  service = args[2];
-
-  CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
-  CHECK_STRING (service);
-  GCPRO2 (bus, service);
-
-  ui_serial = serial;
-  XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Create the message.  */
-  dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
-  if ((dmessage == NULL)
-      || (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED))
-      || (!dbus_message_set_reply_serial (dmessage, serial))
-      || (!dbus_message_set_destination (dmessage, SSDATA (service))))
-    {
-      UNGCPRO;
-      XD_SIGNAL1 (build_string ("Unable to create a error message"));
-    }
-
-  UNGCPRO;
-
-  /* Initialize parameter list of message.  */
-  dbus_message_iter_init_append (dmessage, &iter);
-
-  /* Append parameters to the message.  */
-  for (i = 3; i < nargs; ++i)
-    {
-      dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
-      if (XD_DBUS_TYPE_P (args[i]))
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 2,
-                           SDATA (format2 ("%s", args[i], Qnil)),
-                           SDATA (format2 ("%s", args[i+1], Qnil)));
-         ++i;
-       }
-      else
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 2,
-                           SDATA (format2 ("%s", args[i], Qnil)));
-       }
-
-      /* Check for valid signature.  We use DBUS_TYPE_INVALID as
-        indication that there is no parent type.  */
-      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
-
-      xd_append_arg (dtype, args[i], &iter);
-    }
-
-  /* Send the message.  The message is just added to the outgoing
-     message queue.  */
-  if (!dbus_connection_send (connection, dmessage, NULL))
-    XD_SIGNAL1 (build_string ("Cannot send message"));
-
-  XD_DEBUG_MESSAGE ("Message sent");
-
-  /* Cleanup.  */
-  dbus_message_unref (dmessage);
-
-  /* Return.  */
-  return Qt;
-}
-
-DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
-       doc: /* Send signal SIGNAL on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name SIGNAL is sent from.  PATH is the
-D-Bus object path SERVICE is registered at.  INTERFACE is an interface
-offered by SERVICE.  It must provide signal SIGNAL.
-
-All other arguments ARGS are passed to SIGNAL as arguments.  They are
-converted into D-Bus types via the following rules:
-
-  t and nil => DBUS_TYPE_BOOLEAN
-  number    => DBUS_TYPE_UINT32
-  integer   => DBUS_TYPE_INT32
-  float     => DBUS_TYPE_DOUBLE
-  string    => DBUS_TYPE_STRING
-  list      => DBUS_TYPE_ARRAY
-
-All arguments can be preceded by a type symbol.  For details about
-type symbols, see Info node `(dbus)Type Conversion'.
-
-Example:
-
-\(dbus-send-signal
-  :session "org.gnu.Emacs" "/org/gnu/Emacs"
-  "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
-
-usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service, path, interface, signal;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-  DBusConnection *connection;
-  DBusMessage *dmessage;
-  DBusMessageIter iter;
-  unsigned int dtype;
-  ptrdiff_t i;
-  char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
-
-  /* Check parameters.  */
-  bus = args[0];
-  service = args[1];
-  path = args[2];
-  interface = args[3];
-  signal = args[4];
-
-  CHECK_STRING (service);
-  CHECK_STRING (path);
-  CHECK_STRING (interface);
-  CHECK_STRING (signal);
-  GCPRO5 (bus, service, path, interface, signal);
-
-  XD_DEBUG_MESSAGE ("%s %s %s %s",
-                   SDATA (service),
-                   SDATA (path),
-                   SDATA (interface),
-                   SDATA (signal));
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Create the message.  */
-  dmessage = dbus_message_new_signal (SSDATA (path),
-                                     SSDATA (interface),
-                                     SSDATA (signal));
-  UNGCPRO;
-  if (dmessage == NULL)
-    XD_SIGNAL1 (build_string ("Unable to create a new message"));
-
-  /* Initialize parameter list of message.  */
-  dbus_message_iter_init_append (dmessage, &iter);
-
-  /* Append parameters to the message.  */
-  for (i = 5; i < nargs; ++i)
-    {
-      dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
-      if (XD_DBUS_TYPE_P (args[i]))
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)),
-                           SDATA (format2 ("%s", args[i+1], Qnil)));
-         ++i;
-       }
-      else
-       {
-         XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
-         XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4,
-                           SDATA (format2 ("%s", args[i], Qnil)));
-       }
-
-      /* Check for valid signature.  We use DBUS_TYPE_INVALID as
-        indication that there is no parent type.  */
-      xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
-
-      xd_append_arg (dtype, args[i], &iter);
-    }
-
-  /* Send the message.  The message is just added to the outgoing
-     message queue.  */
-  if (!dbus_connection_send (connection, dmessage, NULL))
-    XD_SIGNAL1 (build_string ("Cannot send message"));
-
-  XD_DEBUG_MESSAGE ("Signal sent");
-
-  /* Cleanup.  */
-  dbus_message_unref (dmessage);
-
-  /* Return.  */
-  return Qt;
-}
-
 /* Read one queued incoming message of the D-Bus BUS.
    BUS is either a Lisp symbol, :system or :session, or a string denoting
    the bus address.  */
@@ -1702,7 +1421,7 @@
   DBusMessage *dmessage;
   DBusMessageIter iter;
   unsigned int dtype;
-  int mtype;
+  unsigned int mtype;
   dbus_uint32_t serial;
   unsigned int ui_serial;
   const char *uname, *path, *interface, *member;
@@ -1744,23 +1463,19 @@
   member = dbus_message_get_member (dmessage);
 
   XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
-                   (mtype == DBUS_MESSAGE_TYPE_INVALID)
-                   ? "DBUS_MESSAGE_TYPE_INVALID"
-                   : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
-                   ? "DBUS_MESSAGE_TYPE_METHOD_CALL"
-                   : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
-                   ? "DBUS_MESSAGE_TYPE_METHOD_RETURN"
-                   : (mtype == DBUS_MESSAGE_TYPE_ERROR)
-                   ? "DBUS_MESSAGE_TYPE_ERROR"
-                   : "DBUS_MESSAGE_TYPE_SIGNAL",
+                   XD_MESSAGE_TYPE_TO_STRING (mtype),
                    ui_serial, uname, path, interface, member,
-                   SDATA (format2 ("%s", args, Qnil)));
-
-  if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
-      || (mtype == DBUS_MESSAGE_TYPE_ERROR))
+                   XD_OBJECT_TO_STRING (args));
+
+  if (mtype == DBUS_MESSAGE_TYPE_INVALID)
+    goto cleanup;
+
+  else if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+          || (mtype == DBUS_MESSAGE_TYPE_ERROR))
     {
       /* Search for a registered function of the message.  */
-      key = list2 (bus, make_fixnum_or_float (serial));
+      key = list3 (QCdbus_registered_serial, bus,
+                  make_fixnum_or_float (serial));
       value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
 
       /* There shall be exactly one entry.  Construct an event.  */
@@ -1777,7 +1492,7 @@
       event.arg = Fcons (value, args);
     }
 
-  else /* (mtype != DBUS_MESSAGE_TYPE_METHOD_RETURN)  */
+  else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL.  */
     {
       /* Vdbus_registered_objects_table requires non-nil interface and
         member.  */
@@ -1785,7 +1500,10 @@
        goto cleanup;
 
       /* Search for a registered function of the message.  */
-      key = list3 (bus, build_string (interface), build_string (member));
+      key = list4 ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
+                  ? QCdbus_registered_method
+                  : QCdbus_registered_signal,
+                  bus, build_string (interface), build_string (member));
       value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
 
       /* Loop over the registered functions.  Construct an event.  */
@@ -1835,8 +1553,7 @@
   /* Store it into the input event queue.  */
   kbd_buffer_store_event (&event);
 
-  XD_DEBUG_MESSAGE ("Event stored: %s",
-                   SDATA (format2 ("%s", event.arg, Qnil)));
+  XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
 
   /* Cleanup.  */
  cleanup:
@@ -1851,8 +1568,8 @@
 static Lisp_Object
 xd_read_message (Lisp_Object bus)
 {
-  /* Open a connection to the bus.  */
-  DBusConnection *connection = xd_initialize (bus, TRUE);
+  /* Retrieve bus address.  */
+  DBusConnection *connection = xd_get_connection_address (bus);
 
   /* Non blocking read of the next available message.  */
   dbus_connection_read_write (connection, 0);
@@ -1869,14 +1586,16 @@
 {
   Lisp_Object busp = Vdbus_registered_buses;
   Lisp_Object bus = Qnil;
+  Lisp_Object key;
 
   /* Find bus related to fd.  */
   if (data != NULL)
     while (!NILP (busp))
       {
-       if ((SYMBOLP (CAR_SAFE (busp)) && XSYMBOL (CAR_SAFE (busp)) == data)
-           || (STRINGP (CAR_SAFE (busp)) && XSTRING (CAR_SAFE (busp)) == data))
-         bus = CAR_SAFE (busp);
+       key = CAR_SAFE (CAR_SAFE (busp));
+       if ((SYMBOLP (key) && XSYMBOL (key) == data)
+           || (STRINGP (key) && XSTRING (key) == data))
+         bus = key;
        busp = CDR_SAFE (busp);
       }
 
@@ -1889,327 +1608,6 @@
   xd_in_read_queued_messages = 0;
 }
 
-DEFUN ("dbus-register-service", Fdbus_register_service, Sdbus_register_service,
-       2, MANY, 0,
-       doc: /* Register known name SERVICE on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name that should be registered.  It must
-be a known name.
-
-FLAGS are keywords, which control how the service name is registered.
-The following keywords are recognized:
-
-`: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.
-
-The function returns a keyword, indicating the result of the
-operation.  One of the following keywords is returned:
-
-`:primary-owner': Service has become the primary owner of the
-requested name.
-
-`:in-queue': Service could not become the primary owner and has been
-placed in the queue.
-
-`:exists': Service is already in the queue.
-
-`:already-owner': Service is already the primary owner.
-
-Example:
-
-\(dbus-register-service :session dbus-service-emacs)
-
-  => :primary-owner.
-
-\(dbus-register-service
-  :session "org.freedesktop.TextEditor"
-  dbus-service-allow-replacement dbus-service-replace-existing)
-
-  => :already-owner.
-
-usage: (dbus-register-service BUS SERVICE &rest FLAGS)  */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service;
-  DBusConnection *connection;
-  ptrdiff_t i;
-  unsigned int value;
-  unsigned int flags = 0;
-  int result;
-  DBusError derror;
-
-  bus = args[0];
-  service = args[1];
-
-  /* Check parameters.  */
-  CHECK_STRING (service);
-
-  /* Process flags.  */
-  for (i = 2; i < nargs; ++i) {
-    value = ((EQ (args[i], QCdbus_request_name_replace_existing))
-            ? DBUS_NAME_FLAG_REPLACE_EXISTING
-            : (EQ (args[i], QCdbus_request_name_allow_replacement))
-            ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT
-            : (EQ (args[i], QCdbus_request_name_do_not_queue))
-            ? DBUS_NAME_FLAG_DO_NOT_QUEUE
-            : -1);
-    if (value == -1)
-      XD_SIGNAL2 (build_string ("Unrecognized name request flag"), args[i]);
-    flags |= value;
-  }
-
-  /* Open a connection to the bus.  */
-  connection = xd_initialize (bus, TRUE);
-
-  /* Request the known name from the bus.  */
-  dbus_error_init (&derror);
-  result = dbus_bus_request_name (connection, SSDATA (service), flags,
-                                 &derror);
-  if (dbus_error_is_set (&derror))
-    XD_ERROR (derror);
-
-  /* Cleanup.  */
-  dbus_error_free (&derror);
-
-  /* Return object.  */
-  switch (result)
-    {
-    case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
-      return QCdbus_request_name_reply_primary_owner;
-    case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
-      return QCdbus_request_name_reply_in_queue;
-    case DBUS_REQUEST_NAME_REPLY_EXISTS:
-      return QCdbus_request_name_reply_exists;
-    case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
-      return QCdbus_request_name_reply_already_owner;
-    default:
-      /* This should not happen.  */
-      XD_SIGNAL2 (build_string ("Could not register service"), service);
-    }
-}
-
-DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
-       6, MANY, 0,
-       doc: /* Register for signal SIGNAL on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-SERVICE is the D-Bus service name used by the sending D-Bus object.
-It can be either a known name or the unique name of the D-Bus object
-sending the signal.  When SERVICE is nil, related signals from all
-D-Bus objects shall be accepted.
-
-PATH is the D-Bus object path SERVICE is registered.  It can also be
-nil if the path name of incoming signals shall not be checked.
-
-INTERFACE is an interface offered by SERVICE.  It must provide SIGNAL.
-HANDLER is a Lisp function to be called when the signal is received.
-It must accept as arguments the values SIGNAL is sending.
-
-All other arguments ARGS, if specified, must be strings.  They stand
-for the respective arguments of the signal in their order, and are
-used for filtering as well.  A nil argument might be used to preserve
-the order.
-
-INTERFACE, SIGNAL and HANDLER must not be nil.  Example:
-
-\(defun my-signal-handler (device)
-  (message "Device %s added" device))
-
-\(dbus-register-signal
-  :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
-  "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
-
-  => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
-      ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
-
-`dbus-register-signal' returns an object, which can be used in
-`dbus-unregister-object' for removing the registration.
-
-usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest 
ARGS) */)
-  (ptrdiff_t nargs, Lisp_Object *args)
-{
-  Lisp_Object bus, service, path, interface, signal, handler;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
-  Lisp_Object uname, key, key1, value;
-  DBusConnection *connection;
-  ptrdiff_t i;
-  char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
-  int rulelen;
-  DBusError derror;
-
-  /* Check parameters.  */
-  bus = args[0];
-  service = args[1];
-  path = args[2];
-  interface = args[3];
-  signal = args[4];
-  handler = args[5];
-
-  if (!NILP (service)) CHECK_STRING (service);
-  if (!NILP (path)) CHECK_STRING (path);
-  CHECK_STRING (interface);
-  CHECK_STRING (signal);
-  if (!FUNCTIONP (handler))
-    wrong_type_argument (Qinvalid_function, handler);
-  GCPRO6 (bus, service, path, interface, signal, handler);
-
-  /* Retrieve unique name of service.  If service is a known name, we
-     will register for the corresponding unique name, if any.  Signals
-     are sent always with the unique name as sender.  Note: the unique
-     name of "org.freedesktop.DBus" is that string itself.  */
-  if ((STRINGP (service))
-      && (SBYTES (service) > 0)
-      && (strcmp (SSDATA (service), DBUS_SERVICE_DBUS) != 0)
-      && (strncmp (SSDATA (service), ":", 1) != 0))
-    uname = call2 (intern ("dbus-get-name-owner"), bus, service);
-  else
-    uname = service;
-
-  /* Create a matching rule if the unique name exists (when no
-     wildcard).  */
-  if (NILP (uname) || (SBYTES (uname) > 0))
-    {
-      /* Open a connection to the bus.  */
-      connection = xd_initialize (bus, TRUE);
-
-      /* Create a rule to receive related signals.  */
-      rulelen = snprintf (rule, sizeof rule,
-                         "type='signal',interface='%s',member='%s'",
-                         SDATA (interface),
-                         SDATA (signal));
-      if (! (0 <= rulelen && rulelen < sizeof rule))
-       string_overflow ();
-
-      /* Add unique name and path to the rule if they are non-nil.  */
-      if (!NILP (uname))
-       {
-         int len = snprintf (rule + rulelen, sizeof rule - rulelen,
-                             ",sender='%s'", SDATA (uname));
-         if (! (0 <= len && len < sizeof rule - rulelen))
-           string_overflow ();
-         rulelen += len;
-       }
-
-      if (!NILP (path))
-       {
-         int len = snprintf (rule + rulelen, sizeof rule - rulelen,
-                             ",path='%s'", SDATA (path));
-         if (! (0 <= len && len < sizeof rule - rulelen))
-           string_overflow ();
-         rulelen += len;
-       }
-
-      /* Add arguments to the rule if they are non-nil.  */
-      for (i = 6; i < nargs; ++i)
-       if (!NILP (args[i]))
-         {
-           int len;
-           CHECK_STRING (args[i]);
-           len = snprintf (rule + rulelen, sizeof rule - rulelen,
-                           ",arg%"pD"d='%s'", i - 6, SDATA (args[i]));
-           if (! (0 <= len && len < sizeof rule - rulelen))
-             string_overflow ();
-           rulelen += len;
-         }
-
-      /* Add the rule to the bus.  */
-      dbus_error_init (&derror);
-      dbus_bus_add_match (connection, rule, &derror);
-      if (dbus_error_is_set (&derror))
-       {
-         UNGCPRO;
-         XD_ERROR (derror);
-       }
-
-      /* Cleanup.  */
-      dbus_error_free (&derror);
-
-      XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
-    }
-
-  /* Create a hash table entry.  */
-  key = list3 (bus, interface, signal);
-  key1 = list5 (uname, service, path, handler, build_string (rule));
-  value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
-
-  if (NILP (Fmember (key1, value)))
-    Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
-
-  /* Return object.  */
-  RETURN_UNGCPRO (list2 (key, list3 (service, path, handler)));
-}
-
-DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
-       6, 7, 0,
-       doc: /* Register for method METHOD on the D-Bus BUS.
-
-BUS is either a Lisp symbol, `:system' or `:session', or a string
-denoting the bus address.
-
-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 the input arguments of METHOD.  The return
-value of HANDLER is used for composing the returning D-Bus message.
-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.*/)
-  (Lisp_Object bus, Lisp_Object service, Lisp_Object path,
-   Lisp_Object interface, Lisp_Object method, Lisp_Object handler,
-   Lisp_Object dont_register_service)
-{
-  Lisp_Object key, key1, value;
-  Lisp_Object args[2] = { bus, service };
-
-  /* Check parameters.  */
-  CHECK_STRING (service);
-  CHECK_STRING (path);
-  CHECK_STRING (interface);
-  CHECK_STRING (method);
-  if (!FUNCTIONP (handler))
-    wrong_type_argument (Qinvalid_function, handler);
-  /* TODO: We must check for a valid service name, otherwise there is
-     a segmentation fault.  */
-
-  /* Request the name.  */
-  if (NILP (dont_register_service))
-    Fdbus_register_service (2, args);
-
-  /* Create a hash table entry.  We use nil for the unique name,
-     because the method might be called from anybody.  */
-  key = list3 (bus, interface, method);
-  key1 = list4 (Qnil, service, path, handler);
-  value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
-
-  if (NILP (Fmember (key1, value)))
-    Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
-
-  /* Return object.  */
-  return list2 (key, list3 (service, path, handler));
-}
-
 
 void
 syms_of_dbusbind (void)
@@ -2218,35 +1616,11 @@
   DEFSYM (Qdbus_init_bus, "dbus-init-bus");
   defsubr (&Sdbus_init_bus);
 
-  DEFSYM (Qdbus_close_bus, "dbus-close-bus");
-  defsubr (&Sdbus_close_bus);
-
   DEFSYM (Qdbus_get_unique_name, "dbus-get-unique-name");
   defsubr (&Sdbus_get_unique_name);
 
-  DEFSYM (Qdbus_call_method, "dbus-call-method");
-  defsubr (&Sdbus_call_method);
-
-  DEFSYM (Qdbus_call_method_asynchronously, "dbus-call-method-asynchronously");
-  defsubr (&Sdbus_call_method_asynchronously);
-
-  DEFSYM (Qdbus_method_return_internal, "dbus-method-return-internal");
-  defsubr (&Sdbus_method_return_internal);
-
-  DEFSYM (Qdbus_method_error_internal, "dbus-method-error-internal");
-  defsubr (&Sdbus_method_error_internal);
-
-  DEFSYM (Qdbus_send_signal, "dbus-send-signal");
-  defsubr (&Sdbus_send_signal);
-
-  DEFSYM (Qdbus_register_service, "dbus-register-service");
-  defsubr (&Sdbus_register_service);
-
-  DEFSYM (Qdbus_register_signal, "dbus-register-signal");
-  defsubr (&Sdbus_register_signal);
-
-  DEFSYM (Qdbus_register_method, "dbus-register-method");
-  defsubr (&Sdbus_register_method);
+  DEFSYM (Qdbus_message_internal, "dbus-message-internal");
+  defsubr (&Sdbus_message_internal);
 
   DEFSYM (Qdbus_error, "dbus-error");
   Fput (Qdbus_error, Qerror_conditions,
@@ -2256,13 +1630,6 @@
 
   DEFSYM (QCdbus_system_bus, ":system");
   DEFSYM (QCdbus_session_bus, ":session");
-  DEFSYM (QCdbus_request_name_allow_replacement, ":allow-replacement");
-  DEFSYM (QCdbus_request_name_replace_existing, ":replace-existing");
-  DEFSYM (QCdbus_request_name_do_not_queue, ":do-not-queue");
-  DEFSYM (QCdbus_request_name_reply_primary_owner, ":primary-owner");
-  DEFSYM (QCdbus_request_name_reply_exists, ":exists");
-  DEFSYM (QCdbus_request_name_reply_in_queue, ":in-queue");
-  DEFSYM (QCdbus_request_name_reply_already_owner, ":already-owner");
   DEFSYM (QCdbus_timeout, ":timeout");
   DEFSYM (QCdbus_type_byte, ":byte");
   DEFSYM (QCdbus_type_boolean, ":boolean");
@@ -2276,19 +1643,73 @@
   DEFSYM (QCdbus_type_string, ":string");
   DEFSYM (QCdbus_type_object_path, ":object-path");
   DEFSYM (QCdbus_type_signature, ":signature");
-
 #ifdef DBUS_TYPE_UNIX_FD
   DEFSYM (QCdbus_type_unix_fd, ":unix-fd");
 #endif
-
   DEFSYM (QCdbus_type_array, ":array");
   DEFSYM (QCdbus_type_variant, ":variant");
   DEFSYM (QCdbus_type_struct, ":struct");
   DEFSYM (QCdbus_type_dict_entry, ":dict-entry");
+  DEFSYM (QCdbus_registered_serial, ":serial");
+  DEFSYM (QCdbus_registered_method, ":method");
+  DEFSYM (QCdbus_registered_signal, ":signal");
+
+  DEFVAR_LISP ("dbus-compiled-version",
+              Vdbus_compiled_version,
+    doc: /* The version of D-Bus Emacs is compiled against.  */);
+#ifdef DBUS_VERSION_STRING
+  Vdbus_compiled_version = make_pure_c_string (DBUS_VERSION_STRING);
+#else
+  Vdbus_compiled_version = Qnil;
+#endif
+
+  DEFVAR_LISP ("dbus-runtime-version",
+              Vdbus_runtime_version,
+    doc: /* The version of D-Bus Emacs runs with.  */);
+  {
+#ifdef DBUS_VERSION
+    int major, minor, micro;
+    char s[1024];
+    dbus_get_version (&major, &minor, &micro);
+    snprintf (s, sizeof s, "%d.%d.%d", major, minor, micro);
+    Vdbus_runtime_version = make_string (s, strlen (s));
+#else
+    Vdbus_runtime_version = Qnil;
+#endif
+  }
+
+  DEFVAR_LISP ("dbus-message-type-invalid",
+              Vdbus_message_type_invalid,
+    doc: /* This value is never a valid message type.  */);
+  Vdbus_message_type_invalid = make_number (DBUS_MESSAGE_TYPE_INVALID);
+
+  DEFVAR_LISP ("dbus-message-type-method-call",
+              Vdbus_message_type_method_call,
+    doc: /* Message type of a method call message.  */);
+  Vdbus_message_type_method_call = make_number (DBUS_MESSAGE_TYPE_METHOD_CALL);
+
+  DEFVAR_LISP ("dbus-message-type-method-return",
+              Vdbus_message_type_method_return,
+    doc: /* Message type of a method return message.  */);
+  Vdbus_message_type_method_return
+    = make_number (DBUS_MESSAGE_TYPE_METHOD_RETURN);
+
+  DEFVAR_LISP ("dbus-message-type-error",
+              Vdbus_message_type_error,
+    doc: /* Message type of an error reply message.  */);
+  Vdbus_message_type_error = make_number (DBUS_MESSAGE_TYPE_ERROR);
+
+  DEFVAR_LISP ("dbus-message-type-signal",
+              Vdbus_message_type_signal,
+    doc: /* Message type of a signal message.  */);
+  Vdbus_message_type_signal = make_number (DBUS_MESSAGE_TYPE_SIGNAL);
 
   DEFVAR_LISP ("dbus-registered-buses",
               Vdbus_registered_buses,
-    doc: /* List of D-Bus buses we are polling for messages.  */);
+    doc: /* Alist of D-Bus buses we are polling for messages.
+
+The key is the symbol or string of the bus, and the value is the
+connection address.  */);
   Vdbus_registered_buses = Qnil;
 
   DEFVAR_LISP ("dbus-registered-objects-table",
@@ -2299,27 +1720,28 @@
 registered interfaces properties, targeted by signals or method calls,
 and for calling handlers in case of non-blocking method call returns.
 
-In the first case, the key in the hash table is the list (BUS
-INTERFACE MEMBER).  BUS is either a Lisp symbol, `:system' or
+In the first case, the key in the hash table is the list (TYPE BUS
+INTERFACE MEMBER).  TYPE is one of the Lisp symbols `:method',
+`:signal' or `:property'.  BUS is either a Lisp symbol, `:system' or
 `:session', or a string denoting the bus address.  INTERFACE is a
 string which denotes a D-Bus interface, and MEMBER, also a string, is
 either a method, a signal or a property INTERFACE is offering.  All
 arguments but BUS must not be nil.
 
-The value in the hash table is a list of quadruple lists
-\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...).
-SERVICE is the service name as registered, UNAME is the corresponding
-unique name.  In case of registered methods and properties, UNAME is
-nil.  PATH is the object path of the sending object.  All of them can
-be nil, which means a wildcard then.  OBJECT is either the handler to
-be called when a D-Bus message, which matches the key criteria,
-arrives (methods and signals), or a cons cell containing the value of
-the property.
-
-For signals, there is also a fifth element RULE, which keeps the match
-string the signal is registered with.
-
-In the second case, the key in the hash table is the list (BUS
+The value in the hash table is a list of quadruple lists \((UNAME
+SERVICE PATH OBJECT [RULE]) ...).  SERVICE is the service name as
+registered, UNAME is the corresponding unique name.  In case of
+registered methods and properties, UNAME is nil.  PATH is the object
+path of the sending object.  All of them can be nil, which means a
+wildcard then.  OBJECT is either the handler to be called when a D-Bus
+message, which matches the key criteria, arrives (TYPE `:method' and
+`:signal'), or a cons cell containing the value of the property (TYPE
+`:property').
+
+For entries of type `:signal', there is also a fifth element RULE,
+which keeps the match string the signal is registered with.
+
+In the second case, the key in the hash table is the list (:serial BUS
 SERIAL).  BUS is either a Lisp symbol, `:system' or `:session', or a
 string denoting the bus address.  SERIAL is the serial number of the
 non-blocking method call, a reply is expected.  Both arguments must


reply via email to

[Prev in Thread] Current Thread [Next in Thread]