]> code.delx.au - gnu-emacs/blobdiff - src/dbusbind.c
Add entries for the EDE and EIEIO manuals.
[gnu-emacs] / src / dbusbind.c
index dcab6fb214c338fe6489879c3894be331b017629..d0233fdab435cfa9ff521172ee2119bc30c75aee 100644 (file)
@@ -1,5 +1,5 @@
 /* Elisp bindings for D-Bus.
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -29,6 +29,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 \f
 /* Subroutines.  */
+Lisp_Object Qdbus_init_bus;
 Lisp_Object Qdbus_get_unique_name;
 Lisp_Object Qdbus_call_method;
 Lisp_Object Qdbus_call_method_asynchronously;
@@ -63,10 +64,39 @@ Lisp_Object Vdbus_registered_functions_table;
 /* Whether to debug D-Bus.  */
 Lisp_Object Vdbus_debug;
 
+/* Whether we are reading a D-Bus event.  */
+int xd_in_read_queued_messages = 0;
+
 \f
 /* We use "xd_" and "XD_" as prefix for all internal symbols, because
    we don't want to poison other namespaces with "dbus_".  */
 
+/* Raise a signal.  If we are reading events, we cannot signal; we
+   throw to xd_read_queued_messages then.  */
+#define XD_SIGNAL1(arg)                                                        \
+  do {                                                                 \
+    if (xd_in_read_queued_messages)                                    \
+      Fthrow (Qdbus_error, Qnil);                                      \
+    else                                                               \
+      xsignal1 (Qdbus_error, arg);                                     \
+  } while (0)
+
+#define XD_SIGNAL2(arg1, arg2)                                         \
+  do {                                                                 \
+    if (xd_in_read_queued_messages)                                    \
+      Fthrow (Qdbus_error, Qnil);                                      \
+    else                                                               \
+      xsignal2 (Qdbus_error, arg1, arg2);                              \
+  } while (0)
+
+#define XD_SIGNAL3(arg1, arg2, arg3)                                   \
+  do {                                                                 \
+    if (xd_in_read_queued_messages)                                    \
+      Fthrow (Qdbus_error, Qnil);                                      \
+    else                                                               \
+      xsignal3 (Qdbus_error, arg1, arg2, arg3);                                \
+  } while (0)
+
 /* Raise a Lisp error from a D-Bus ERROR.  */
 #define XD_ERROR(error)                                                        \
   do {                                                                 \
@@ -76,7 +106,7 @@ Lisp_Object Vdbus_debug;
     /* Remove the trailing newline.  */                                        \
     if (strchr (s, '\n') != NULL)                                      \
       s[strlen (s) - 1] = '\0';                                                \
-    xsignal1 (Qdbus_error, build_string (s));                          \
+    XD_SIGNAL1 (build_string (s));                                     \
   } while (0)
 
 /* Macros for debugging.  In order to enable them, build with
@@ -94,7 +124,7 @@ Lisp_Object Vdbus_debug;
     if (!valid_lisp_object_p (object))                                 \
       {                                                                        \
        XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__);            \
-       xsignal1 (Qdbus_error, build_string ("Assertion failure"));     \
+       XD_SIGNAL1 (build_string ("Assertion failure"));                \
       }                                                                        \
   } while (0)
 
@@ -126,30 +156,38 @@ Lisp_Object Vdbus_debug;
    || (type ==  DBUS_TYPE_OBJECT_PATH)                                 \
    || (type ==  DBUS_TYPE_SIGNATURE))
 
+/* This was a macro.  On Solaris 2.11 it was said to compile for
+   hours, when optimzation is enabled.  So we have transferred it into
+   a function.  */
 /* Determine the DBusType of a given Lisp symbol.  OBJECT must be one
    of the predefined D-Bus type symbols.  */
-#define XD_SYMBOL_TO_DBUS_TYPE(object)                                 \
-  ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE                    \
-   : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN            \
-   : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16                        \
-   : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16              \
-   : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32                        \
-   : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32              \
-   : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64                        \
-   : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64              \
-   : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE              \
-   : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING              \
-   : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH    \
-   : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE                \
-   : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY                        \
-   : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT            \
-   : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT              \
-   : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY      \
-   : DBUS_TYPE_INVALID)
+static int
+xd_symbol_to_dbus_type (object)
+     Lisp_Object object;
+{
+  return
+    ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
+     : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN
+     : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16
+     : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16
+     : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32
+     : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32
+     : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64
+     : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64
+     : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE
+     : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING
+     : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH
+     : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE
+     : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
+     : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
+     : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
+     : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY
+     : DBUS_TYPE_INVALID);
+}
 
 /* Check whether a Lisp symbol is a predefined D-Bus type symbol.  */
 #define XD_DBUS_TYPE_P(object)                                         \
-  (SYMBOLP (object) && ((XD_SYMBOL_TO_DBUS_TYPE (object) != DBUS_TYPE_INVALID)))
+  (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
 
 /* Determine the DBusType of a given Lisp OBJECT.  It is used to
    convert Lisp objects, being arguments of `dbus-call-method' or
@@ -161,12 +199,12 @@ Lisp_Object Vdbus_debug;
    : (INTEGERP (object)) ? DBUS_TYPE_INT32                             \
    : (FLOATP (object)) ? DBUS_TYPE_DOUBLE                              \
    : (STRINGP (object)) ? DBUS_TYPE_STRING                             \
-   : (XD_DBUS_TYPE_P (object)) ? XD_SYMBOL_TO_DBUS_TYPE (object)       \
+   : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object)       \
    : (CONSP (object))                                                  \
    ? ((XD_DBUS_TYPE_P (CAR_SAFE (object)))                             \
-      ? ((XD_BASIC_DBUS_TYPE (XD_SYMBOL_TO_DBUS_TYPE (CAR_SAFE (object)))) \
+      ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
         ? DBUS_TYPE_ARRAY                                              \
-        : XD_SYMBOL_TO_DBUS_TYPE (CAR_SAFE (object)))                  \
+        : xd_symbol_to_dbus_type (CAR_SAFE (object)))                  \
       : DBUS_TYPE_ARRAY)                                               \
    : DBUS_TYPE_INVALID)
 
@@ -181,7 +219,7 @@ Lisp_Object Vdbus_debug;
    a type symbol.  PARENT_TYPE is the DBusType of a container this
    signature is embedded, or DBUS_TYPE_INVALID.  It is needed for the
    check that DBUS_TYPE_DICT_ENTRY occurs only as array element.  */
-void
+static void
 xd_signature (signature, dtype, parent_type, object)
      char *signature;
      unsigned int dtype, parent_type;
@@ -353,7 +391,7 @@ xd_signature (signature, dtype, parent_type, object)
    objects, being arguments of `dbus-call-method' or
    `dbus-send-signal', into corresponding C values appended as
    arguments to a D-Bus message.  */
-void
+static void
 xd_append_arg (dtype, object, iter)
      unsigned int dtype;
      Lisp_Object object;
@@ -370,8 +408,7 @@ xd_append_arg (dtype, object, iter)
          unsigned char val = XUINT (object) & 0xFF;
          XD_DEBUG_MESSAGE ("%c %d", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -380,8 +417,7 @@ xd_append_arg (dtype, object, iter)
          dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
          XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -390,8 +426,7 @@ xd_append_arg (dtype, object, iter)
          dbus_int16_t val = XINT (object);
          XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -400,8 +435,7 @@ xd_append_arg (dtype, object, iter)
          dbus_uint16_t val = XUINT (object);
          XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -410,8 +444,7 @@ xd_append_arg (dtype, object, iter)
          dbus_int32_t val = XINT (object);
          XD_DEBUG_MESSAGE ("%c %d", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -420,8 +453,7 @@ xd_append_arg (dtype, object, iter)
          dbus_uint32_t val = XUINT (object);
          XD_DEBUG_MESSAGE ("%c %u", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -430,8 +462,7 @@ xd_append_arg (dtype, object, iter)
          dbus_int64_t val = XINT (object);
          XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
@@ -440,18 +471,18 @@ xd_append_arg (dtype, object, iter)
          dbus_uint64_t val = XUINT (object);
          XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
 
       case DBUS_TYPE_DOUBLE:
-       XD_DEBUG_MESSAGE ("%c %f", dtype, XFLOAT_DATA (object));
-       if (!dbus_message_iter_append_basic (iter, dtype,
-                                            &XFLOAT_DATA (object)))
-         xsignal2 (Qdbus_error,
-                   build_string ("Unable to append argument"), object);
-       return;
+       {
+         double val = XFLOAT_DATA (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);
+         return;
+       }
 
       case DBUS_TYPE_STRING:
       case DBUS_TYPE_OBJECT_PATH:
@@ -460,8 +491,7 @@ xd_append_arg (dtype, object, iter)
          char *val = SDATA (Fstring_make_unibyte (object));
          XD_DEBUG_MESSAGE ("%c %s", dtype, val);
          if (!dbus_message_iter_append_basic (iter, dtype, &val))
-           xsignal2 (Qdbus_error,
-                     build_string ("Unable to append argument"), object);
+           XD_SIGNAL2 (build_string ("Unable to append argument"), object);
          return;
        }
       }
@@ -509,9 +539,8 @@ xd_append_arg (dtype, object, iter)
                            SDATA (format2 ("%s", object, Qnil)));
          if (!dbus_message_iter_open_container (iter, dtype,
                                                 signature, &subiter))
-           xsignal3 (Qdbus_error,
-                     build_string ("Cannot open container"),
-                     make_number (dtype), build_string (signature));
+           XD_SIGNAL3 (build_string ("Cannot open container"),
+                       make_number (dtype), build_string (signature));
          break;
 
        case DBUS_TYPE_VARIANT:
@@ -523,9 +552,8 @@ xd_append_arg (dtype, object, iter)
                            SDATA (format2 ("%s", object, Qnil)));
          if (!dbus_message_iter_open_container (iter, dtype,
                                                 signature, &subiter))
-           xsignal3 (Qdbus_error,
-                     build_string ("Cannot open container"),
-                     make_number (dtype), build_string (signature));
+           XD_SIGNAL3 (build_string ("Cannot open container"),
+                       make_number (dtype), build_string (signature));
          break;
 
        case DBUS_TYPE_STRUCT:
@@ -534,9 +562,8 @@ xd_append_arg (dtype, object, iter)
          XD_DEBUG_MESSAGE ("%c %s", dtype,
                            SDATA (format2 ("%s", object, Qnil)));
          if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
-           xsignal2 (Qdbus_error,
-                     build_string ("Cannot open container"),
-                     make_number (dtype));
+           XD_SIGNAL2 (build_string ("Cannot open container"),
+                       make_number (dtype));
          break;
        }
 
@@ -553,9 +580,8 @@ xd_append_arg (dtype, object, iter)
 
       /* Close the subiteration.  */
       if (!dbus_message_iter_close_container (iter, &subiter))
-       xsignal2 (Qdbus_error,
-                 build_string ("Cannot close container"),
-                 make_number (dtype));
+       XD_SIGNAL2 (build_string ("Cannot close container"),
+                   make_number (dtype));
     }
 }
 
@@ -563,7 +589,7 @@ xd_append_arg (dtype, object, iter)
    a converted Lisp object.  The type DTYPE of the argument of the
    D-Bus message must be a valid DBusType.  Compound D-Bus types
    result always in a Lisp list.  */
-Lisp_Object
+static Lisp_Object
 xd_retrieve_arg (dtype, iter)
      unsigned int dtype;
      DBusMessageIter *iter;
@@ -667,7 +693,7 @@ xd_retrieve_arg (dtype, iter)
 
 /* Initialize D-Bus connection.  BUS is a Lisp symbol, either :system
    or :session.  It tells which D-Bus to be initialized.  */
-DBusConnection *
+static DBusConnection *
 xd_initialize (bus)
      Lisp_Object bus;
 {
@@ -676,8 +702,13 @@ xd_initialize (bus)
 
   /* Parameter check.  */
   CHECK_SYMBOL (bus);
-  if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
-    xsignal2 (Qdbus_error, build_string ("Wrong bus name"), 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);
 
   /* Open a connection to the bus.  */
   dbus_error_init (&derror);
@@ -691,12 +722,102 @@ xd_initialize (bus)
     XD_ERROR (derror);
 
   if (connection == NULL)
-    xsignal2 (Qdbus_error, build_string ("No connection"), bus);
+    XD_SIGNAL2 (build_string ("No connection to bus"), bus);
+
+  /* Cleanup.  */
+  dbus_error_free (&derror);
 
   /* Return the result.  */
   return connection;
 }
 
+
+/* Add connection file descriptor to input_wait_mask, in order to
+   let select() detect, whether a new message has been arrived.  */
+dbus_bool_t
+xd_add_watch (watch, data)
+     DBusWatch *watch;
+     void *data;
+{
+  /* We check only for incoming data.  */
+  if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE)
+    {
+#if HAVE_DBUS_WATCH_GET_UNIX_FD
+      /* TODO: Reverse these on Win32, which prefers the opposite. */
+      int fd = dbus_watch_get_unix_fd(watch);
+      if (fd == -1)
+       fd = dbus_watch_get_socket(watch);
+#else
+      int fd = dbus_watch_get_fd(watch);
+#endif
+      XD_DEBUG_MESSAGE ("%d", fd);
+
+      if (fd == -1)
+       return FALSE;
+
+      /* Add the file descriptor to input_wait_mask.  */
+      add_keyboard_wait_descriptor (fd);
+    }
+
+  /* Return.  */
+  return TRUE;
+}
+
+/* Remove connection file descriptor from input_wait_mask.  */
+void
+xd_remove_watch (watch, data)
+     DBusWatch *watch;
+     void *data;
+{
+  /* We check only for incoming data.  */
+  if (dbus_watch_get_flags (watch) & DBUS_WATCH_READABLE)
+    {
+#if HAVE_DBUS_WATCH_GET_UNIX_FD
+      /* TODO: Reverse these on Win32, which prefers the opposite. */
+      int fd = dbus_watch_get_unix_fd(watch);
+      if (fd == -1)
+       fd = dbus_watch_get_socket(watch);
+#else
+      int fd = dbus_watch_get_fd(watch);
+#endif
+      XD_DEBUG_MESSAGE ("%d", fd);
+
+      if (fd == -1)
+       return;
+
+      /* Remove the file descriptor from input_wait_mask.  */
+      delete_keyboard_wait_descriptor (fd);
+    }
+
+  /* Return.  */
+  return;
+}
+
+DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
+       doc: /* Initialize connection to D-Bus BUS.
+This is an internal function, it shall not be used outside dbus.el.  */)
+     (bus)
+     Lisp_Object bus;
+{
+  DBusConnection *connection;
+
+  /* Check parameters.  */
+  CHECK_SYMBOL (bus);
+
+  /* Open a connection to the bus.  */
+  connection = xd_initialize (bus);
+
+  /* Add the watch functions.  */
+  if (!dbus_connection_set_watch_functions (connection,
+                                           xd_add_watch,
+                                           xd_remove_watch,
+                                           NULL, NULL, NULL))
+    XD_SIGNAL1 (build_string ("Cannot add watch functions"));
+
+  /* Return.  */
+  return Qnil;
+}
+
 DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
        1, 1, 0,
        doc: /* Return the unique name of Emacs registered at D-Bus BUS.  */)
@@ -715,7 +836,7 @@ DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
   /* Request the name.  */
   name = dbus_bus_get_unique_name (connection);
   if (name == NULL)
-    xsignal1 (Qdbus_error, build_string ("No unique name available"));
+    XD_SIGNAL1 (build_string ("No unique name available"));
 
   /* Return.  */
   return build_string (name);
@@ -732,7 +853,7 @@ offered by SERVICE.  It must provide METHOD.
 
 If the parameter `:timeout' is given, the following integer TIMEOUT
 specifies the maximun number of milliseconds the method call must
-return.  The default value is 25.000.  If the method call doesn't
+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
@@ -836,7 +957,7 @@ usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TI
                                           SDATA (method));
   UNGCPRO;
   if (dmessage == NULL)
-    xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
+    XD_SIGNAL1 (build_string ("Unable to create a new message"));
 
   /* Check for timeout parameter.  */
   if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
@@ -887,7 +1008,7 @@ usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TI
     XD_ERROR (derror);
 
   if (reply == NULL)
-    xsignal1 (Qdbus_error, build_string ("No reply"));
+    XD_SIGNAL1 (build_string ("No reply"));
 
   XD_DEBUG_MESSAGE ("Message sent");
 
@@ -912,6 +1033,7 @@ usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TI
     }
 
   /* Cleanup.  */
+  dbus_error_free (&derror);
   dbus_message_unref (dmessage);
   dbus_message_unref (reply);
 
@@ -934,11 +1056,12 @@ 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.
+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 maximun number of milliseconds the method call must
-return.  The default value is 25.000.  If the method call doesn't
+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
@@ -954,7 +1077,7 @@ converted into D-Bus types via the following rules:
 All arguments can be preceded by a type symbol.  For details about
 type symbols, see Info node `(dbus)Type Conversion'.
 
-The function returns a key into the hash table
+Unless HANDLER is nil, the function returns a key into the hash table
 `dbus-registered-functions-table'.  The corresponding entry in the
 hash table is removed, when the return message has been arrived, and
 HANDLER is called.
@@ -999,7 +1122,7 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
   CHECK_STRING (path);
   CHECK_STRING (interface);
   CHECK_STRING (method);
-  if (!FUNCTIONP (handler))
+  if (!NILP (handler) && !FUNCTIONP (handler))
     wrong_type_argument (intern ("functionp"), handler);
   GCPRO6 (bus, service, path, interface, method, handler);
 
@@ -1018,7 +1141,7 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
                                           SDATA (interface),
                                           SDATA (method));
   if (dmessage == NULL)
-    xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
+    XD_SIGNAL1 (build_string ("Unable to create a new message"));
 
   /* Check for timeout parameter.  */
   if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
@@ -1058,18 +1181,34 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
       xd_append_arg (dtype, args[i], &iter);
     }
 
-  /* Send the message.  The message is just added to the outgoing
-     message queue.  */
-  if (!dbus_connection_send_with_reply (connection, dmessage, NULL, timeout))
-    xsignal1 (Qdbus_error, build_string ("Cannot send message"));
+  if (!NILP (handler))
+    {
+      /* Send the message.  The message is just added to the outgoing
+        message queue.  */
+      if (!dbus_connection_send_with_reply (connection, dmessage,
+                                           NULL, timeout))
+       XD_SIGNAL1 (build_string ("Cannot send message"));
 
-  XD_DEBUG_MESSAGE ("Message sent");
+      /* The result is the key in Vdbus_registered_functions_table.  */
+      result = (list2 (bus, make_number (dbus_message_get_serial (dmessage))));
 
-  /* The result is the key in Vdbus_registered_functions_table.  */
-  result = (list2 (bus, make_number (dbus_message_get_serial (dmessage))));
+      /* Create a hash table entry.  */
+      Fputhash (result, handler, Vdbus_registered_functions_table);
+    }
+  else
+    {
+      /* 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"));
 
-  /* Create a hash table entry.  */
-  Fputhash (result, handler, Vdbus_registered_functions_table);
+      result = Qnil;
+    }
+
+  /* Flush connection to ensure the message is handled.  */
+  dbus_connection_flush (connection);
+
+  XD_DEBUG_MESSAGE ("Message sent");
 
   /* Cleanup.  */
   dbus_message_unref (dmessage);
@@ -1120,8 +1259,7 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS)  */)
       || (!dbus_message_set_destination (dmessage, SDATA (service))))
     {
       UNGCPRO;
-      xsignal1 (Qdbus_error,
-               build_string ("Unable to create a return message"));
+      XD_SIGNAL1 (build_string ("Unable to create a return message"));
     }
 
   UNGCPRO;
@@ -1159,7 +1297,7 @@ usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS)  */)
   /* Send the message.  The message is just added to the outgoing
      message queue.  */
   if (!dbus_connection_send (connection, dmessage, NULL))
-    xsignal1 (Qdbus_error, build_string ("Cannot send message"));
+    XD_SIGNAL1 (build_string ("Cannot send message"));
 
   /* Flush connection to ensure the message is handled.  */
   dbus_connection_flush (connection);
@@ -1216,8 +1354,7 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS)  */)
       || (!dbus_message_set_destination (dmessage, SDATA (service))))
     {
       UNGCPRO;
-      xsignal1 (Qdbus_error,
-               build_string ("Unable to create a error message"));
+      XD_SIGNAL1 (build_string ("Unable to create a error message"));
     }
 
   UNGCPRO;
@@ -1255,7 +1392,7 @@ usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS)  */)
   /* Send the message.  The message is just added to the outgoing
      message queue.  */
   if (!dbus_connection_send (connection, dmessage, NULL))
-    xsignal1 (Qdbus_error, build_string ("Cannot send message"));
+    XD_SIGNAL1 (build_string ("Cannot send message"));
 
   /* Flush connection to ensure the message is handled.  */
   dbus_connection_flush (connection);
@@ -1340,7 +1477,7 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)  */)
                                      SDATA (signal));
   UNGCPRO;
   if (dmessage == NULL)
-    xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
+    XD_SIGNAL1 (build_string ("Unable to create a new message"));
 
   /* Initialize parameter list of message.  */
   dbus_message_iter_init_append (dmessage, &iter);
@@ -1375,7 +1512,7 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)  */)
   /* Send the message.  The message is just added to the outgoing
      message queue.  */
   if (!dbus_connection_send (connection, dmessage, NULL))
-    xsignal1 (Qdbus_error, build_string ("Cannot send message"));
+    XD_SIGNAL1 (build_string ("Cannot send message"));
 
   /* Flush connection to ensure the message is handled.  */
   dbus_connection_flush (connection);
@@ -1389,9 +1526,46 @@ usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)  */)
   return Qt;
 }
 
+/* Check, whether there is pending input in the message queue of the
+   D-Bus BUS.  BUS is a Lisp symbol, either :system or :session.  */
+int
+xd_get_dispatch_status (bus)
+     Lisp_Object bus;
+{
+  DBusConnection *connection;
+
+  /* Open a connection to the bus.  */
+  connection = xd_initialize (bus);
+
+  /* Non blocking read of the next available message.  */
+  dbus_connection_read_write (connection, 0);
+
+  /* Return.  */
+  return
+    (dbus_connection_get_dispatch_status (connection)
+     == DBUS_DISPATCH_DATA_REMAINS)
+    ? TRUE : FALSE;
+}
+
+/* Check for queued incoming messages from the system and session buses.  */
+int
+xd_pending_messages ()
+{
+
+  /* Vdbus_registered_functions_table will be initialized as hash
+     table in dbus.el.  When this package isn't loaded yet, it doesn't
+     make sense to handle D-Bus messages.  */
+  return (HASH_TABLE_P (Vdbus_registered_functions_table)
+         ? (xd_get_dispatch_status (QCdbus_system_bus)
+            || ((getenv ("DBUS_SESSION_BUS_ADDRESS") != NULL)
+                ? xd_get_dispatch_status (QCdbus_session_bus)
+                : FALSE))
+         : FALSE);
+}
+
 /* Read queued incoming message of the D-Bus BUS.  BUS is a Lisp
    symbol, either :system or :session.  */
-Lisp_Object
+static Lisp_Object
 xd_read_message (bus)
      Lisp_Object bus;
 {
@@ -1541,8 +1715,10 @@ xd_read_message (bus)
   XD_DEBUG_MESSAGE ("Event stored: %s",
                    SDATA (format2 ("%s", event.arg, Qnil)));
 
+  /* Cleanup.  */
  cleanup:
   dbus_message_unref (dmessage);
+
   RETURN_UNGCPRO (Qnil);
 }
 
@@ -1557,10 +1733,10 @@ xd_read_queued_messages ()
      Lisp errors during the call.  */
   if (HASH_TABLE_P (Vdbus_registered_functions_table))
     {
-      internal_condition_case_1 (xd_read_message, QCdbus_system_bus,
-                                Qerror, Fidentity);
-      internal_condition_case_1 (xd_read_message, QCdbus_session_bus,
-                                Qerror, Fidentity);
+      xd_in_read_queued_messages = 1;
+      internal_catch (Qdbus_error, xd_read_message, QCdbus_system_bus);
+      internal_catch (Qdbus_error, xd_read_message, QCdbus_session_bus);
+      xd_in_read_queued_messages = 0;
     }
 }
 
@@ -1646,7 +1822,7 @@ usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARG
       /* When there is no unique name, we mark it with an empty
         string.  */
       if (NILP (uname))
-       uname = build_string ("");
+       uname = empty_unibyte_string;
     }
   else
     uname = service;
@@ -1695,6 +1871,9 @@ usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARG
          XD_ERROR (derror);
        }
 
+      /* Cleanup.  */
+      dbus_error_free (&derror);
+
       XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
     }
 
@@ -1763,6 +1942,9 @@ used for composing the returning D-Bus message.  */)
   if (NILP (Fmember (key1, value)))
     Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
 
+  /* Cleanup.  */
+  dbus_error_free (&derror);
+
   /* Return object.  */
   return list2 (key, list3 (service, path, handler));
 }
@@ -1772,6 +1954,10 @@ void
 syms_of_dbusbind ()
 {
 
+  Qdbus_init_bus = intern ("dbus-init-bus");
+  staticpro (&Qdbus_init_bus);
+  defsubr (&Sdbus_init_bus);
+
   Qdbus_get_unique_name = intern ("dbus-get-unique-name");
   staticpro (&Qdbus_get_unique_name);
   defsubr (&Sdbus_get_unique_name);