Mercurial > emacs
changeset 109961:25b9c8c975be
* dbusbind.c: Accept UNIX domain sockets as bus address.
(Fdbus_close_bus): New function.
(Vdbus_registered_buses): New variable.
(xd_initialize): Implement string as bus address.
(Fdbus_init_bus): Add bus to Vdbus_registered_buses).
(Fdbus_get_unique_name, Fdbus_call_method)
(Fdbus_call_method_asynchronously, Fdbus_method_return_internal)
(Fdbus_method_error_internal, Fdbus_send_signal)
(Fdbus_register_signal, Fdbus_register_method): Remove bus type
check. This is done in xd_initialize_bus. Adapt doc string, if
necessary.
(xd_pending_messages, xd_read_queued_messages): Loop over buses in
Vdbus_registered_buses.
(Vdbus_registered_objects_table): Create hash.
author | Michael Albinus <michael.albinus@gmx.de> |
---|---|
date | Mon, 23 Aug 2010 15:02:00 +0200 |
parents | 16358be4a799 |
children | aa3e4f636621 |
files | src/ChangeLog src/dbusbind.c |
diffstat | 2 files changed, 169 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog Mon Aug 23 14:54:09 2010 +0200 +++ b/src/ChangeLog Mon Aug 23 15:02:00 2010 +0200 @@ -1,3 +1,20 @@ +2010-08-23 Michael Albinus <michael.albinus@gmx.de> + + * dbusbind.c: Accept UNIX domain sockets as bus address. + (Fdbus_close_bus): New function. + (Vdbus_registered_buses): New variable. + (xd_initialize): Implement string as bus address. + (Fdbus_init_bus): Add bus to Vdbus_registered_buses). + (Fdbus_get_unique_name, Fdbus_call_method) + (Fdbus_call_method_asynchronously, Fdbus_method_return_internal) + (Fdbus_method_error_internal, Fdbus_send_signal) + (Fdbus_register_signal, Fdbus_register_method): Remove bus type + check. This is done in xd_initialize_bus. Adapt doc string, if + necessary. + (xd_pending_messages, xd_read_queued_messages): Loop over buses in + Vdbus_registered_buses. + (Vdbus_registered_objects_table): Create hash. + 2010-08-22 Juri Linkov <juri@jurta.org> * keyboard.c (Fexecute_extended_command): Move reading a command name
--- a/src/dbusbind.c Mon Aug 23 14:54:09 2010 +0200 +++ b/src/dbusbind.c Mon Aug 23 15:02:00 2010 +0200 @@ -31,6 +31,7 @@ /* 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; @@ -59,6 +60,9 @@ Lisp_Object QCdbus_type_array, QCdbus_type_variant; Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry; +/* Registered buses. */ +Lisp_Object Vdbus_registered_buses; + /* Hash table which keeps function definitions. */ Lisp_Object Vdbus_registered_objects_table; @@ -111,7 +115,7 @@ } 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 { \ @@ -713,10 +717,10 @@ } } -/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system - or :session. It tells which D-Bus to initialize. If RAISE_ERROR - is non-zero signal an error when the connection cannot 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 (Lisp_Object bus, int raise_error) { @@ -724,34 +728,66 @@ DBusError derror; /* Parameter check. */ - 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; + 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; + /* 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)) - if (raise_error) - XD_ERROR (derror); - else - connection = NULL; + { + 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) XD_SIGNAL2 (build_string ("No connection to bus"), bus); @@ -794,7 +830,8 @@ } /* Remove connection file descriptor from input_wait_mask. DATA is - the used bus, either QCdbus_system_bus or QCdbus_session_bus. */ + the used bus, either a string or QCdbus_system_bus or + QCdbus_session_bus. */ void xd_remove_watch (DBusWatch *watch, void *data) { @@ -830,15 +867,11 @@ } 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. */) + doc: /* Initialize connection to D-Bus BUS. */) (Lisp_Object bus) { DBusConnection *connection; - /* Check parameters. */ - CHECK_SYMBOL (bus); - /* Open a connection to the bus. */ connection = xd_initialize (bus, TRUE); @@ -850,6 +883,28 @@ NULL, (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); + + /* 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; } @@ -862,9 +917,6 @@ DBusConnection *connection; const char *name; - /* Check parameters. */ - CHECK_SYMBOL (bus); - /* Open a connection to the bus. */ connection = xd_initialize (bus, TRUE); @@ -880,7 +932,8 @@ 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 @@ -967,7 +1020,6 @@ interface = args[3]; method = args[4]; - CHECK_SYMBOL (bus); CHECK_STRING (service); CHECK_STRING (path); CHECK_STRING (interface); @@ -1082,7 +1134,8 @@ 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 @@ -1148,7 +1201,6 @@ method = args[4]; handler = args[5]; - CHECK_SYMBOL (bus); CHECK_STRING (service); CHECK_STRING (path); CHECK_STRING (interface); @@ -1271,7 +1323,6 @@ serial = args[1]; service = args[2]; - CHECK_SYMBOL (bus); CHECK_NUMBER (serial); CHECK_STRING (service); GCPRO3 (bus, serial, service); @@ -1363,7 +1414,6 @@ serial = args[1]; service = args[2]; - CHECK_SYMBOL (bus); CHECK_NUMBER (serial); CHECK_STRING (service); GCPRO3 (bus, serial, service); @@ -1436,7 +1486,8 @@ 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 @@ -1480,7 +1531,6 @@ interface = args[3]; signal = args[4]; - CHECK_SYMBOL (bus); CHECK_STRING (service); CHECK_STRING (path); CHECK_STRING (interface); @@ -1552,7 +1602,8 @@ } /* Check, whether there is pending input in the message queue of the - D-Bus BUS. BUS is a Lisp symbol, either :system or :session. */ + D-Bus BUS. BUS is either a Lisp symbol, :system or :session, or a + string denoting the bus address. */ int xd_get_dispatch_status (Lisp_Object bus) { @@ -1572,24 +1623,31 @@ ? TRUE : FALSE; } -/* Check for queued incoming messages from the system and session buses. */ +/* Check for queued incoming messages from the buses. */ int xd_pending_messages (void) { + Lisp_Object busp = Vdbus_registered_buses; - /* Vdbus_registered_objects_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_objects_table) - ? (xd_get_dispatch_status (QCdbus_system_bus) - || ((getenv ("DBUS_SESSION_BUS_ADDRESS") != NULL) - ? xd_get_dispatch_status (QCdbus_session_bus) - : FALSE)) - : FALSE); + while (!NILP (busp)) + { + /* We do not want to have an autolaunch for the session bus. */ + if (EQ ((CAR_SAFE (busp)), QCdbus_session_bus) + && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) + continue; + + if (xd_get_dispatch_status (CAR_SAFE (busp))) + return TRUE; + + busp = CDR_SAFE (busp); + } + + return FALSE; } -/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp - symbol, either :system or :session. */ +/* Read 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 Lisp_Object xd_read_message (Lisp_Object bus) { @@ -1746,29 +1804,28 @@ RETURN_UNGCPRO (Qnil); } -/* Read queued incoming messages from the system and session buses. */ +/* Read queued incoming messages from all buses. */ void xd_read_queued_messages (void) { + Lisp_Object busp = Vdbus_registered_buses; - /* Vdbus_registered_objects_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_objects_table)) + xd_in_read_queued_messages = 1; + while (!NILP (busp)) { - 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; + /* We ignore all Lisp errors during the call. */ + internal_catch (Qdbus_error, xd_read_message, CAR_SAFE (busp)); + busp = CDR_SAFE (busp); } + xd_in_read_queued_messages = 0; } 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 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 @@ -1822,7 +1879,6 @@ signal = args[4]; handler = args[5]; - CHECK_SYMBOL (bus); if (!NILP (service)) CHECK_STRING (service); if (!NILP (path)) CHECK_STRING (path); CHECK_STRING (interface); @@ -1915,7 +1971,8 @@ 6, 6, 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. @@ -1933,7 +1990,6 @@ DBusError derror; /* Check parameters. */ - CHECK_SYMBOL (bus); CHECK_STRING (service); CHECK_STRING (path); CHECK_STRING (interface); @@ -1978,6 +2034,10 @@ 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); @@ -2074,18 +2134,25 @@ QCdbus_type_dict_entry = intern_c_string (":dict-entry"); staticpro (&QCdbus_type_dict_entry); + 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 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, a signal or a property -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 OBJECT) (UNAME SERVICE PATH OBJECT) ...). @@ -2097,15 +2164,18 @@ 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 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_objects_table in dbus.el, because - we need to define a hash table function first. */ - Vdbus_registered_objects_table = Qnil; +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. */);