/* Elisp bindings for D-Bus.
- Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2007-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-#include "config.h"
+#include <config.h>
#ifdef HAVE_DBUS
-#include <stdlib.h>
#include <stdio.h>
#include <dbus/dbus.h>
+#include <setjmp.h>
#include "lisp.h"
#include "frame.h"
#include "termhooks.h"
#include "keyboard.h"
+#include "process.h"
\f
/* Subroutines. */
+Lisp_Object Qdbus_init_bus;
+Lisp_Object Qdbus_close_bus;
Lisp_Object Qdbus_get_unique_name;
Lisp_Object Qdbus_call_method;
Lisp_Object Qdbus_call_method_asynchronously;
Lisp_Object Qdbus_method_return_internal;
Lisp_Object Qdbus_method_error_internal;
Lisp_Object Qdbus_send_signal;
+Lisp_Object Qdbus_register_service;
Lisp_Object Qdbus_register_signal;
Lisp_Object Qdbus_register_method;
/* Lisp symbol for method call timeout. */
Lisp_Object QCdbus_timeout;
+/* Lisp symbols for name request flags. */
+Lisp_Object QCdbus_request_name_allow_replacement;
+Lisp_Object QCdbus_request_name_replace_existing;
+Lisp_Object QCdbus_request_name_do_not_queue;
+
+/* Lisp symbols for name request replies. */
+Lisp_Object QCdbus_request_name_reply_primary_owner;
+Lisp_Object QCdbus_request_name_reply_in_queue;
+Lisp_Object QCdbus_request_name_reply_exists;
+Lisp_Object QCdbus_request_name_reply_already_owner;
+
/* Lisp symbols of D-Bus types. */
Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
Lisp_Object QCdbus_type_double, QCdbus_type_string;
Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
+#ifdef DBUS_TYPE_UNIX_FD
+Lisp_Object QCdbus_type_unix_fd;
+#endif
Lisp_Object QCdbus_type_array, QCdbus_type_variant;
Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
-/* Hash table which keeps function definitions. */
-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;
} while (0)
/* Macros for debugging. In order to enable them, build with
- "make MYCPPFLAGS='-DDBUS_DEBUG -Wall'". */
+ "MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
#ifdef DBUS_DEBUG
#define XD_DEBUG_MESSAGE(...) \
do { \
#endif
/* Check whether TYPE is a basic DBusType. */
+#ifdef DBUS_TYPE_UNIX_FD
+#define XD_BASIC_DBUS_TYPE(type) \
+ ((type == DBUS_TYPE_BYTE) \
+ || (type == DBUS_TYPE_BOOLEAN) \
+ || (type == DBUS_TYPE_INT16) \
+ || (type == DBUS_TYPE_UINT16) \
+ || (type == DBUS_TYPE_INT32) \
+ || (type == DBUS_TYPE_UINT32) \
+ || (type == DBUS_TYPE_INT64) \
+ || (type == DBUS_TYPE_UINT64) \
+ || (type == DBUS_TYPE_DOUBLE) \
+ || (type == DBUS_TYPE_STRING) \
+ || (type == DBUS_TYPE_OBJECT_PATH) \
+ || (type == DBUS_TYPE_SIGNATURE) \
+ || (type == DBUS_TYPE_UNIX_FD))
+#else
#define XD_BASIC_DBUS_TYPE(type) \
((type == DBUS_TYPE_BYTE) \
|| (type == DBUS_TYPE_BOOLEAN) \
|| (type == DBUS_TYPE_STRING) \
|| (type == DBUS_TYPE_OBJECT_PATH) \
|| (type == DBUS_TYPE_SIGNATURE))
+#endif
/* 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
/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
of the predefined D-Bus type symbols. */
static int
-xd_symbol_to_dbus_type (object)
- Lisp_Object object;
+xd_symbol_to_dbus_type (Lisp_Object object)
{
return
((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
: (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
+#ifdef DBUS_TYPE_UNIX_FD
+ : (EQ (object, QCdbus_type_unix_fd)) ? DBUS_TYPE_UNIX_FD
+#endif
: (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
: (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
: (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
static void
-xd_signature (signature, dtype, parent_type, object)
- char *signature;
- unsigned int dtype, parent_type;
- Lisp_Object object;
+xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lisp_Object object)
{
unsigned int subtype;
Lisp_Object elt;
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;
`dbus-send-signal', into corresponding C values appended as
arguments to a D-Bus message. */
static void
-xd_append_arg (dtype, object, iter)
- unsigned int dtype;
- Lisp_Object object;
- DBusMessageIter *iter;
+xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
{
char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
DBusMessageIter subiter;
switch (dtype)
{
case DBUS_TYPE_BYTE:
+ CHECK_NUMBER (object);
{
unsigned char val = XUINT (object) & 0xFF;
XD_DEBUG_MESSAGE ("%c %d", dtype, val);
}
case DBUS_TYPE_INT16:
+ CHECK_NUMBER (object);
{
dbus_int16_t val = XINT (object);
XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
}
case DBUS_TYPE_UINT16:
+ CHECK_NUMBER (object);
{
dbus_uint16_t val = XUINT (object);
XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
}
case DBUS_TYPE_INT32:
+ CHECK_NUMBER (object);
{
dbus_int32_t val = XINT (object);
XD_DEBUG_MESSAGE ("%c %d", dtype, val);
}
case DBUS_TYPE_UINT32:
+#ifdef DBUS_TYPE_UNIX_FD
+ case DBUS_TYPE_UNIX_FD:
+#endif
+ CHECK_NUMBER (object);
{
dbus_uint32_t val = XUINT (object);
XD_DEBUG_MESSAGE ("%c %u", dtype, val);
}
case DBUS_TYPE_INT64:
+ CHECK_NUMBER (object);
{
dbus_int64_t val = XINT (object);
XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
}
case DBUS_TYPE_UINT64:
+ CHECK_NUMBER (object);
{
dbus_uint64_t val = XUINT (object);
XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
}
case DBUS_TYPE_DOUBLE:
- XD_DEBUG_MESSAGE ("%c %f", dtype, XFLOAT_DATA (object));
- if (!dbus_message_iter_append_basic (iter, dtype,
- &XFLOAT_DATA (object)))
- XD_SIGNAL2 (build_string ("Unable to append argument"), object);
- return;
+ CHECK_FLOAT (object);
+ {
+ 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:
case DBUS_TYPE_SIGNATURE:
+ CHECK_STRING (object);
{
- char *val = SDATA (Fstring_make_unibyte (object));
+ /* We need to send a valid UTF-8 string. We could encode `object'
+ but by not encoding it, we guarantee it's valid utf-8, even if
+ it contains eight-bit-bytes. Of course, you can still send
+ manually-crafted junk by passing a unibyte string. */
+ char *val = SDATA (object);
XD_DEBUG_MESSAGE ("%c %s", dtype, val);
if (!dbus_message_iter_append_basic (iter, dtype, &val))
XD_SIGNAL2 (build_string ("Unable to append argument"), object);
D-Bus message must be a valid DBusType. Compound D-Bus types
result always in a Lisp list. */
static Lisp_Object
-xd_retrieve_arg (dtype, iter)
- unsigned int dtype;
- DBusMessageIter *iter;
+xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
{
switch (dtype)
}
case DBUS_TYPE_INT16:
+ {
+ dbus_int16_t val;
+ dbus_message_iter_get_basic (iter, &val);
+ XD_DEBUG_MESSAGE ("%c %d", dtype, val);
+ return make_number (val);
+ }
+
case DBUS_TYPE_UINT16:
{
dbus_uint16_t val;
}
case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t val;
+ dbus_message_iter_get_basic (iter, &val);
+ XD_DEBUG_MESSAGE ("%c %d", dtype, val);
+ return make_fixnum_or_float (val);
+ }
+
case DBUS_TYPE_UINT32:
+#ifdef DBUS_TYPE_UNIX_FD
+ case DBUS_TYPE_UNIX_FD:
+#endif
{
- /* Assignment to EMACS_INT stops GCC whining about limited
- range of data type. */
dbus_uint32_t val;
- EMACS_INT val1;
dbus_message_iter_get_basic (iter, &val);
XD_DEBUG_MESSAGE ("%c %d", dtype, val);
- val1 = val;
- return make_fixnum_or_float (val1);
+ return make_fixnum_or_float (val);
}
case DBUS_TYPE_INT64:
+ {
+ dbus_int64_t val;
+ dbus_message_iter_get_basic (iter, &val);
+ XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
+ return make_fixnum_or_float (val);
+ }
+
case DBUS_TYPE_UINT64:
{
dbus_uint64_t val;
{
Lisp_Object result;
struct gcpro gcpro1;
- result = Qnil;
- GCPRO1 (result);
DBusMessageIter subiter;
int subtype;
+ result = Qnil;
+ GCPRO1 (result);
dbus_message_iter_recurse (iter, &subiter);
while ((subtype = dbus_message_iter_get_arg_type (&subiter))
!= DBUS_TYPE_INVALID)
}
}
-/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
- or :session. It tells which D-Bus to be initialized. */
+/* 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. */
static DBusConnection *
-xd_initialize (bus)
- Lisp_Object bus;
+xd_initialize (Lisp_Object bus, int raise_error)
{
DBusConnection *connection;
DBusError derror;
- int fd;
/* Parameter check. */
- CHECK_SYMBOL (bus);
- if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
- XD_SIGNAL2 (build_string ("Wrong bus name"), bus);
+ 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 (EQ (bus, QCdbus_system_bus))
- connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
+ if (STRINGP (bus))
+ connection = dbus_connection_open (SDATA (bus), &derror);
else
- connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ 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))
- XD_ERROR (derror);
+ {
+ if (raise_error)
+ XD_ERROR (derror);
+ else
+ connection = NULL;
+ }
- if (connection == NULL)
- XD_SIGNAL2 (build_string ("No connection"), 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 (connection != NULL)
+ {
+ if (STRINGP (bus))
+ dbus_bus_register (connection, &derror);
+ else
+ dbus_connection_set_exit_on_disconnect (connection, FALSE);
+ }
- /* Add connection file descriptor to input_wait_mask, in order to
- let select() detect, whether a new message has been arrived. */
- if (dbus_connection_get_unix_fd (connection, &fd))
- add_keyboard_wait_descriptor (fd);
+ if (dbus_error_is_set (&derror))
+ {
+ if (raise_error)
+ XD_ERROR (derror);
+ else
+ connection = NULL;
+ }
+
+ if (connection == NULL && raise_error)
+ XD_SIGNAL2 (build_string ("No connection to bus"), bus);
/* Cleanup. */
dbus_error_free (&derror);
return connection;
}
+/* Return the file descriptor for WATCH, -1 if not found. */
+static int
+xd_find_watch_fd (DBusWatch *watch)
+{
+#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
+ return fd;
+}
+
+/* Prototype. */
+static void
+xd_read_queued_messages (int fd, void *data, int for_read);
+
+/* Start monitoring WATCH for possible I/O. */
+static dbus_bool_t
+xd_add_watch (DBusWatch *watch, void *data)
+{
+ unsigned int flags = dbus_watch_get_flags (watch);
+ 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));
+
+ if (fd == -1)
+ return FALSE;
+
+ if (dbus_watch_get_enabled (watch))
+ {
+ if (flags & DBUS_WATCH_WRITABLE)
+ add_write_fd (fd, xd_read_queued_messages, data);
+ if (flags & DBUS_WATCH_READABLE)
+ add_read_fd (fd, xd_read_queued_messages, data);
+ }
+ return TRUE;
+}
+
+/* Stop monitoring WATCH for possible I/O.
+ DATA is the used bus, either a string or QCdbus_system_bus or
+ QCdbus_session_bus. */
+static void
+xd_remove_watch (DBusWatch *watch, void *data)
+{
+ unsigned int flags = dbus_watch_get_flags (watch);
+ int fd = xd_find_watch_fd (watch);
+
+ XD_DEBUG_MESSAGE ("fd %d", fd);
+
+ if (fd == -1)
+ return;
+
+ /* Unset session environment. */
+ if (data != NULL && data == (void*) XHASH (QCdbus_session_bus))
+ {
+ XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
+ unsetenv ("DBUS_SESSION_BUS_ADDRESS");
+ }
+
+ if (flags & DBUS_WATCH_WRITABLE)
+ delete_write_fd (fd);
+ if (flags & DBUS_WATCH_READABLE)
+ delete_read_fd (fd);
+}
+
+/* Toggle monitoring WATCH for possible I/O. */
+static void
+xd_toggle_watch (DBusWatch *watch, void *data)
+{
+ if (dbus_watch_get_enabled (watch))
+ xd_add_watch (watch, data);
+ else
+ 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;
+
+ /* Open a connection to the bus. */
+ connection = xd_initialize (bus, TRUE);
+
+ /* Add the watch functions. We pass also the bus as data, in order
+ to distinguish between the busses in xd_remove_watch. */
+ if (!dbus_connection_set_watch_functions (connection,
+ xd_add_watch,
+ xd_remove_watch,
+ xd_toggle_watch,
+ (void*) XHASH (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);
+
+ /* We do not want to abort. */
+ putenv ("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;
+}
+
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. */)
- (bus)
- Lisp_Object bus;
+ (Lisp_Object bus)
{
DBusConnection *connection;
const char *name;
- /* Check parameters. */
- CHECK_SYMBOL (bus);
-
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Request the name. */
name = dbus_bus_get_unique_name (connection);
DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
doc: /* Call METHOD on the D-Bus BUS.
-BUS is either the symbol `:system' or the symbol `:session'.
+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 maximun number of milliseconds the method call must
-return. The default value is 25.000. If the method call doesn't
+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
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
=> "i686"
usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TIMEOUT &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, service, path, interface, method;
Lisp_Object result;
interface = args[3];
method = args[4];
- CHECK_SYMBOL (bus);
CHECK_STRING (service);
CHECK_STRING (path);
CHECK_STRING (interface);
SDATA (method));
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create the message. */
dmessage = dbus_message_new_method_call (SDATA (service),
Sdbus_call_method_asynchronously, 6, MANY, 0,
doc: /* Call METHOD on the D-Bus BUS asynchronously.
-BUS is either the symbol `:system' or the symbol `:session'.
+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
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
+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
type symbols, see Info node `(dbus)Type Conversion'.
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
+`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:
-| i686
usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLER &optional :timeout TIMEOUT &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, service, path, interface, method, handler;
Lisp_Object result;
method = args[4];
handler = args[5];
- CHECK_SYMBOL (bus);
CHECK_STRING (service);
CHECK_STRING (path);
CHECK_STRING (interface);
SDATA (method));
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create the message. */
dmessage = dbus_message_new_method_call (SDATA (service),
NULL, timeout))
XD_SIGNAL1 (build_string ("Cannot send message"));
- /* The result is the key in Vdbus_registered_functions_table. */
+ /* The result is the key in Vdbus_registered_objects_table. */
result = (list2 (bus, make_number (dbus_message_get_serial (dmessage))));
/* Create a hash table entry. */
- Fputhash (result, handler, Vdbus_registered_functions_table);
+ Fputhash (result, handler, Vdbus_registered_objects_table);
}
else
{
result = Qnil;
}
- /* Flush connection to ensure the message is handled. */
- dbus_connection_flush (connection);
-
XD_DEBUG_MESSAGE ("Message sent");
/* Cleanup. */
This is an internal function, it shall not be used outside dbus.el.
usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, serial, service;
struct gcpro gcpro1, gcpro2, gcpro3;
serial = args[1];
service = args[2];
- CHECK_SYMBOL (bus);
CHECK_NUMBER (serial);
CHECK_STRING (service);
GCPRO3 (bus, serial, service);
- XD_DEBUG_MESSAGE ("%d %s ", XUINT (serial), SDATA (service));
+ XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) XUINT (serial), SDATA (service));
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create the message. */
dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
if (!dbus_connection_send (connection, dmessage, NULL))
XD_SIGNAL1 (build_string ("Cannot send message"));
- /* Flush connection to ensure the message is handled. */
- dbus_connection_flush (connection);
-
XD_DEBUG_MESSAGE ("Message sent");
/* Cleanup. */
This is an internal function, it shall not be used outside dbus.el.
usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, serial, service;
struct gcpro gcpro1, gcpro2, gcpro3;
serial = args[1];
service = args[2];
- CHECK_SYMBOL (bus);
CHECK_NUMBER (serial);
CHECK_STRING (service);
GCPRO3 (bus, serial, service);
- XD_DEBUG_MESSAGE ("%d %s ", XUINT (serial), SDATA (service));
+ XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) XUINT (serial), SDATA (service));
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create the message. */
dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
if (!dbus_connection_send (connection, dmessage, NULL))
XD_SIGNAL1 (build_string ("Cannot send message"));
- /* Flush connection to ensure the message is handled. */
- dbus_connection_flush (connection);
-
XD_DEBUG_MESSAGE ("Message sent");
/* Cleanup. */
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 the symbol `:system' or the symbol `:session'.
+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
"org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, service, path, interface, signal;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
interface = args[3];
signal = args[4];
- CHECK_SYMBOL (bus);
CHECK_STRING (service);
CHECK_STRING (path);
CHECK_STRING (interface);
SDATA (signal));
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create the message. */
dmessage = dbus_message_new_signal (SDATA (path),
if (!dbus_connection_send (connection, dmessage, NULL))
XD_SIGNAL1 (build_string ("Cannot send message"));
- /* Flush connection to ensure the message is handled. */
- dbus_connection_flush (connection);
-
XD_DEBUG_MESSAGE ("Signal sent");
/* Cleanup. */
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)
- || (xd_get_dispatch_status (QCdbus_session_bus))))
- : FALSE);
-}
-
-/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
- symbol, either :system or :session. */
-static Lisp_Object
-xd_read_message (bus)
- Lisp_Object bus;
+/* 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. */
+static void
+xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
{
Lisp_Object args, key, value;
struct gcpro gcpro1;
struct input_event event;
- DBusConnection *connection;
DBusMessage *dmessage;
DBusMessageIter iter;
unsigned int dtype;
int mtype, serial;
const char *uname, *path, *interface, *member;
- /* Open a connection to the bus. */
- connection = xd_initialize (bus);
-
- /* Non blocking read of the next available message. */
- dbus_connection_read_write (connection, 0);
dmessage = dbus_connection_pop_message (connection);
/* Return if there is no queued message. */
if (dmessage == NULL)
- return Qnil;
+ return;
/* Collect the parameters. */
args = Qnil;
{
/* Search for a registered function of the message. */
key = list2 (bus, make_number (serial));
- value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
+ value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
/* There shall be exactly one entry. Construct an event. */
if (NILP (value))
goto cleanup;
/* Remove the entry. */
- Fremhash (key, Vdbus_registered_functions_table);
+ Fremhash (key, Vdbus_registered_objects_table);
/* Construct an event. */
EVENT_INIT (event);
else /* (mtype != DBUS_MESSAGE_TYPE_METHOD_RETURN) */
{
- /* Vdbus_registered_functions_table requires non-nil interface
- and member. */
+ /* Vdbus_registered_objects_table requires non-nil interface and
+ member. */
if ((interface == NULL) || (member == NULL))
goto cleanup;
/* Search for a registered function of the message. */
key = list3 (bus, build_string (interface), build_string (member));
- value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
+ value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
/* Loop over the registered functions. Construct an event. */
while (!NILP (value))
cleanup:
dbus_message_unref (dmessage);
- RETURN_UNGCPRO (Qnil);
+ UNGCPRO;
}
-/* Read queued incoming messages from the system and session buses. */
-void
-xd_read_queued_messages ()
+/* Read queued incoming messages of the D-Bus BUS.
+ BUS is either a Lisp symbol, :system or :session, or a string denoting
+ the bus address. */
+static Lisp_Object
+xd_read_message (Lisp_Object bus)
+{
+ /* Open a connection to the bus. */
+ DBusConnection *connection = xd_initialize (bus, TRUE);
+
+ /* Non blocking read of the next available message. */
+ dbus_connection_read_write (connection, 0);
+
+ while (dbus_connection_get_dispatch_status (connection)
+ != DBUS_DISPATCH_COMPLETE)
+ xd_read_message_1 (connection, bus);
+ return Qnil;
+}
+
+/* Callback called when something is ready to read or write. */
+static void
+xd_read_queued_messages (int fd, void *data, int for_read)
{
+ Lisp_Object busp = Vdbus_registered_buses;
+ Lisp_Object bus = Qnil;
+
+ /* Find bus related to fd. */
+ if (data != NULL)
+ while (!NILP (busp))
+ {
+ if (data == (void*) XHASH (CAR_SAFE (busp)))
+ bus = CAR_SAFE (busp);
+ busp = CDR_SAFE (busp);
+ }
+
+ if (NILP(bus))
+ return;
+
+ /* We ignore all Lisp errors during the call. */
+ xd_in_read_queued_messages = 1;
+ internal_catch (Qdbus_error, xd_read_message, bus);
+ 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:
- /* 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. Furthermore, we ignore all
- Lisp errors during the call. */
- if (HASH_TABLE_P (Vdbus_registered_functions_table))
+`: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) */)
+ (int nargs, register Lisp_Object *args)
+{
+ Lisp_Object bus, service;
+ struct gcpro gcpro1, gcpro2;
+ DBusConnection *connection;
+ unsigned int 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, SDATA (service), flags,
+ &derror);
+ if (dbus_error_is_set (&derror))
+ XD_ERROR (derror);
+
+ /* Cleanup. */
+ dbus_error_free (&derror);
+
+ /* Return object. */
+ switch (result)
{
- 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;
+ 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);
}
}
6, MANY, 0,
doc: /* Register for signal SIGNAL on the D-Bus BUS.
-BUS is either the symbol `:system' or the symbol `:session'.
+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
`dbus-unregister-object' for removing the registration.
usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
- (nargs, args)
- int nargs;
- register Lisp_Object *args;
+ (int nargs, register Lisp_Object *args)
{
Lisp_Object bus, service, path, interface, signal, handler;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
signal = args[4];
handler = args[5];
- CHECK_SYMBOL (bus);
if (!NILP (service)) CHECK_STRING (service);
if (!NILP (path)) CHECK_STRING (path);
CHECK_STRING (interface);
if (NILP (uname) || (SBYTES (uname) > 0))
{
/* Open a connection to the bus. */
- connection = xd_initialize (bus);
+ connection = xd_initialize (bus, TRUE);
/* Create a rule to receive related signals. */
sprintf (rule,
/* Create a hash table entry. */
key = list3 (bus, interface, signal);
key1 = list4 (uname, service, path, handler);
- value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
+ value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
if (NILP (Fmember (key1, value)))
- Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
+ 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, 6, 0,
+ 6, 7, 0,
doc: /* Register for method METHOD on the D-Bus BUS.
-BUS is either the symbol `:system' or the symbol `:session'.
+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.
-
-PATH is the D-Bus object path SERVICE is registered. INTERFACE is the
-interface offered by SERVICE. It must provide METHOD. HANDLER is a
-Lisp function to be called when a method call is received. It must
-accept the input arguments of METHOD. The return value of HANDLER is
-used for composing the returning D-Bus message. */)
- (bus, service, path, interface, method, handler)
- Lisp_Object bus, service, path, interface, method, handler;
+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.
+
+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 use 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;
- DBusConnection *connection;
- int result;
DBusError derror;
+ Lisp_Object args[2] = { bus, service };
/* Check parameters. */
- CHECK_SYMBOL (bus);
CHECK_STRING (service);
CHECK_STRING (path);
CHECK_STRING (interface);
/* TODO: We must check for a valid service name, otherwise there is
a segmentation fault. */
- /* Open a connection to the bus. */
- connection = xd_initialize (bus);
-
- /* Request the known name from the bus. We can ignore the result,
- it is set to -1 if there is an error - kind of redundancy. */
- dbus_error_init (&derror);
- result = dbus_bus_request_name (connection, SDATA (service), 0, &derror);
- if (dbus_error_is_set (&derror))
- XD_ERROR (derror);
+ /* Request the name. */
+ if (NILP (dont_register_service))
+ Fdbus_register_service (2, args);
- /* Create a hash table entry. */
+ /* 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_functions_table, Qnil);
+ value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
- /* We use nil for the unique name, because the method might be
- called from everybody. */
if (NILP (Fmember (key1, value)))
- Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
-
- /* Cleanup. */
- dbus_error_free (&derror);
+ Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
/* Return object. */
return list2 (key, list3 (service, path, handler));
\f
void
-syms_of_dbusbind ()
+syms_of_dbusbind (void)
{
- Qdbus_get_unique_name = intern ("dbus-get-unique-name");
+ Qdbus_init_bus = intern_c_string ("dbus-init-bus");
+ staticpro (&Qdbus_init_bus);
+ defsubr (&Sdbus_init_bus);
+
+ Qdbus_close_bus = intern_c_string ("dbus-close-bus");
+ staticpro (&Qdbus_close_bus);
+ defsubr (&Sdbus_close_bus);
+
+ Qdbus_get_unique_name = intern_c_string ("dbus-get-unique-name");
staticpro (&Qdbus_get_unique_name);
defsubr (&Sdbus_get_unique_name);
- Qdbus_call_method = intern ("dbus-call-method");
+ Qdbus_call_method = intern_c_string ("dbus-call-method");
staticpro (&Qdbus_call_method);
defsubr (&Sdbus_call_method);
- Qdbus_call_method_asynchronously = intern ("dbus-call-method-asynchronously");
+ Qdbus_call_method_asynchronously = intern_c_string ("dbus-call-method-asynchronously");
staticpro (&Qdbus_call_method_asynchronously);
defsubr (&Sdbus_call_method_asynchronously);
- Qdbus_method_return_internal = intern ("dbus-method-return-internal");
+ Qdbus_method_return_internal = intern_c_string ("dbus-method-return-internal");
staticpro (&Qdbus_method_return_internal);
defsubr (&Sdbus_method_return_internal);
- Qdbus_method_error_internal = intern ("dbus-method-error-internal");
+ Qdbus_method_error_internal = intern_c_string ("dbus-method-error-internal");
staticpro (&Qdbus_method_error_internal);
defsubr (&Sdbus_method_error_internal);
- Qdbus_send_signal = intern ("dbus-send-signal");
+ Qdbus_send_signal = intern_c_string ("dbus-send-signal");
staticpro (&Qdbus_send_signal);
defsubr (&Sdbus_send_signal);
- Qdbus_register_signal = intern ("dbus-register-signal");
+ Qdbus_register_service = intern_c_string ("dbus-register-service");
+ staticpro (&Qdbus_register_service);
+ defsubr (&Sdbus_register_service);
+
+ Qdbus_register_signal = intern_c_string ("dbus-register-signal");
staticpro (&Qdbus_register_signal);
defsubr (&Sdbus_register_signal);
- Qdbus_register_method = intern ("dbus-register-method");
+ Qdbus_register_method = intern_c_string ("dbus-register-method");
staticpro (&Qdbus_register_method);
defsubr (&Sdbus_register_method);
- Qdbus_error = intern ("dbus-error");
+ Qdbus_error = intern_c_string ("dbus-error");
staticpro (&Qdbus_error);
Fput (Qdbus_error, Qerror_conditions,
list2 (Qdbus_error, Qerror));
Fput (Qdbus_error, Qerror_message,
- build_string ("D-Bus error"));
+ make_pure_c_string ("D-Bus error"));
- QCdbus_system_bus = intern (":system");
+ QCdbus_system_bus = intern_c_string (":system");
staticpro (&QCdbus_system_bus);
- QCdbus_session_bus = intern (":session");
+ QCdbus_session_bus = intern_c_string (":session");
staticpro (&QCdbus_session_bus);
- QCdbus_timeout = intern (":timeout");
+ QCdbus_request_name_allow_replacement = intern_c_string (":allow-replacement");
+ staticpro (&QCdbus_request_name_allow_replacement);
+
+ QCdbus_request_name_replace_existing = intern_c_string (":replace-existing");
+ staticpro (&QCdbus_request_name_replace_existing);
+
+ QCdbus_request_name_do_not_queue = intern_c_string (":do-not-queue");
+ staticpro (&QCdbus_request_name_do_not_queue);
+
+ QCdbus_request_name_reply_primary_owner = intern_c_string (":primary-owner");
+ staticpro (&QCdbus_request_name_reply_primary_owner);
+
+ QCdbus_request_name_reply_exists = intern_c_string (":exists");
+ staticpro (&QCdbus_request_name_reply_exists);
+
+ QCdbus_request_name_reply_in_queue = intern_c_string (":in-queue");
+ staticpro (&QCdbus_request_name_reply_in_queue);
+
+ QCdbus_request_name_reply_already_owner = intern_c_string (":already-owner");
+ staticpro (&QCdbus_request_name_reply_already_owner);
+
+ QCdbus_timeout = intern_c_string (":timeout");
staticpro (&QCdbus_timeout);
- QCdbus_type_byte = intern (":byte");
+ QCdbus_type_byte = intern_c_string (":byte");
staticpro (&QCdbus_type_byte);
- QCdbus_type_boolean = intern (":boolean");
+ QCdbus_type_boolean = intern_c_string (":boolean");
staticpro (&QCdbus_type_boolean);
- QCdbus_type_int16 = intern (":int16");
+ QCdbus_type_int16 = intern_c_string (":int16");
staticpro (&QCdbus_type_int16);
- QCdbus_type_uint16 = intern (":uint16");
+ QCdbus_type_uint16 = intern_c_string (":uint16");
staticpro (&QCdbus_type_uint16);
- QCdbus_type_int32 = intern (":int32");
+ QCdbus_type_int32 = intern_c_string (":int32");
staticpro (&QCdbus_type_int32);
- QCdbus_type_uint32 = intern (":uint32");
+ QCdbus_type_uint32 = intern_c_string (":uint32");
staticpro (&QCdbus_type_uint32);
- QCdbus_type_int64 = intern (":int64");
+ QCdbus_type_int64 = intern_c_string (":int64");
staticpro (&QCdbus_type_int64);
- QCdbus_type_uint64 = intern (":uint64");
+ QCdbus_type_uint64 = intern_c_string (":uint64");
staticpro (&QCdbus_type_uint64);
- QCdbus_type_double = intern (":double");
+ QCdbus_type_double = intern_c_string (":double");
staticpro (&QCdbus_type_double);
- QCdbus_type_string = intern (":string");
+ QCdbus_type_string = intern_c_string (":string");
staticpro (&QCdbus_type_string);
- QCdbus_type_object_path = intern (":object-path");
+ QCdbus_type_object_path = intern_c_string (":object-path");
staticpro (&QCdbus_type_object_path);
- QCdbus_type_signature = intern (":signature");
+ QCdbus_type_signature = intern_c_string (":signature");
staticpro (&QCdbus_type_signature);
- QCdbus_type_array = intern (":array");
+#ifdef DBUS_TYPE_UNIX_FD
+ QCdbus_type_unix_fd = intern_c_string (":unix-fd");
+ staticpro (&QCdbus_type_unix_fd);
+#endif
+
+ QCdbus_type_array = intern_c_string (":array");
staticpro (&QCdbus_type_array);
- QCdbus_type_variant = intern (":variant");
+ QCdbus_type_variant = intern_c_string (":variant");
staticpro (&QCdbus_type_variant);
- QCdbus_type_struct = intern (":struct");
+ QCdbus_type_struct = intern_c_string (":struct");
staticpro (&QCdbus_type_struct);
- QCdbus_type_dict_entry = intern (":dict-entry");
+ QCdbus_type_dict_entry = intern_c_string (":dict-entry");
staticpro (&QCdbus_type_dict_entry);
- DEFVAR_LISP ("dbus-registered-functions-table",
- &Vdbus_registered_functions_table,
+ DEFVAR_LISP ("dbus-registered-buses",
+ Vdbus_registered_buses,
+ doc: /* List of D-Bus buses we are polling for messages. */);
+ Vdbus_registered_buses = Qnil;
+
+ DEFVAR_LISP ("dbus-registered-objects-table",
+ Vdbus_registered_objects_table,
doc: /* Hash table of registered functions for D-Bus.
-There are two different uses of the hash table: for calling registered
-functions, targeted by signals or method calls, and for calling
-handlers in case of non-blocking method call returns.
+
+There are two different uses of the hash table: for accessing
+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 the symbol `:system' or the symbol
-`:session'. INTERFACE is a string which denotes a D-Bus interface,
-and MEMBER, also a string, is either a method or a signal INTERFACE is
-offering. All arguments but BUS must not be nil.
+INTERFACE MEMBER). 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 HANDLER) (UNAME SERVICE PATH HANDLER) ...).
+\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...).
SERVICE is the service name as registered, UNAME is the corresponding
-unique name. PATH is the object path of the sending object. All of
-them can be nil, which means a wildcard then. HANDLER is the function
-to be called when a D-Bus message, which matches the key criteria,
-arrives.
-
-In the second case, the key in the hash table is the list (BUS SERIAL).
-BUS is either the symbol `:system' or the symbol `:session'. SERIAL
-is the serial number of the non-blocking method call, a reply is
-expected. Both arguments must not be nil. The value in the hash
-table is HANDLER, the function to be called when the D-Bus reply
-message arrives. */);
- /* We initialize Vdbus_registered_functions_table in dbus.el,
- because we need to define a hash table function first. */
- Vdbus_registered_functions_table = Qnil;
-
- DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
+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.
+
+In the second case, the key in the hash table is the 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
+non-blocking method call, a reply is expected. Both arguments must
+not be nil. The value in the hash table is HANDLER, the function to
+be called when the D-Bus reply message arrives. */);
+ {
+ Lisp_Object args[2];
+ args[0] = QCtest;
+ args[1] = Qequal;
+ Vdbus_registered_objects_table = Fmake_hash_table (2, args);
+ }
+
+ DEFVAR_LISP ("dbus-debug", Vdbus_debug,
doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
#ifdef DBUS_DEBUG
Vdbus_debug = Qt;
+ /* We can also set environment variable DBUS_VERBOSE=1 in order to
+ see more traces. This requires libdbus-1 to be configured with
+ --enable-verbose-mode. */
#else
Vdbus_debug = Qnil;
#endif
- Fprovide (intern ("dbusbind"), Qnil);
+ Fprovide (intern_c_string ("dbusbind"), Qnil);
}
#endif /* HAVE_DBUS */
-/* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
- (do not change this comment) */