aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2012-04-22 16:11:43 +0200
committerMichael Albinus2012-04-22 16:11:43 +0200
commitdcbf5805ac7ade7fc83f3d209e2d56f029918402 (patch)
treeca2d664f76032c4cd39d798ae659e23a30f0b4f8
parentcf20dee0248049a925275f54381cf63bb2017e35 (diff)
downloademacs-dcbf5805ac7ade7fc83f3d209e2d56f029918402.tar.gz
emacs-dcbf5805ac7ade7fc83f3d209e2d56f029918402.zip
Move functions from C to Lisp. Make non-blocking method calls
the default. Implement further D-Bus standard interfaces. * configure.in (dbus_validate_bus_name, dbus_validate_path) (dbus_validate_interface, dbus_validate_member): Check also for these library functions * dbusbind.c (DBUS_NUM_MESSAGE_TYPES): Declare. (QCdbus_request_name_allow_replacement) (QCdbus_request_name_replace_existing) (QCdbus_request_name_do_not_queue) (QCdbus_request_name_reply_primary_owner) (QCdbus_request_name_reply_in_queue) (QCdbus_request_name_reply_exists) (QCdbus_request_name_reply_already_owner): Move to dbus.el. (QCdbus_registered_serial, QCdbus_registered_method) (QCdbus_registered_signal): New Lisp objects. (XD_DEBUG_MESSAGE): Use sizeof. (XD_MESSAGE_TYPE_TO_STRING, XD_OBJECT_TO_STRING) (XD_DBUS_VALIDATE_BUS_ADDRESS, XD_DBUS_VALIDATE_OBJECT) (XD_DBUS_VALIDATE_BUS_NAME, XD_DBUS_VALIDATE_PATH) (XD_DBUS_VALIDATE_INTERFACE, XD_DBUS_VALIDATE_MEMBER): New macros. (XD_CHECK_DBUS_SERIAL): Rename from CHECK_DBUS_SERIAL_GET_SERIAL. (xd_signature, xd_append_arg): Allow float for integer types. (xd_get_connection_references): New function. (xd_get_connection_address): Rename from xd_initialize. Return cached address. (xd_remove_watch): Do not unset $DBUS_SESSION_BUS_ADDRESS. (xd_close_bus): Rename from Fdbus_close_bus. Not needed on Lisp level. (Fdbus_init_bus): New optional arg PRIVATE. Cache address. Return number of recounts. (Fdbus_get_unique_name): Make stronger parameter check. (Fdbus_message_internal): New defun. (Fdbus_call_method, Fdbus_call_method_asynchronously) (Fdbus_method_return_internal, Fdbus_method_error_internal) (Fdbus_send_signal, Fdbus_register_service) (Fdbus_register_signal, Fdbus_register_method): Move to dbus.el. (xd_read_message_1): Obey new structure of Vdbus_registered_objects. (xd_read_queued_messages): Obey new structure of Vdbus_registered_buses. (Vdbus_compiled_version, Vdbus_runtime_version) (Vdbus_message_type_invalid, Vdbus_message_type_method_call) (Vdbus_message_type_method_return, Vdbus_message_type_error) (Vdbus_message_type_signal): New defvars. (Vdbus_registered_buses, Vdbus_registered_objects_table): Adapt docstring. * net/dbus.el (dbus-message-internal): Declare function. Remove unneeded function declarations. (defvar dbus-message-type-invalid, dbus-message-type-method-call) (dbus-message-type-method-return, dbus-message-type-error) (dbus-message-type-signal): Declare variables. Remove local definitions. (dbus-interface-dbus, dbus-interface-peer) (dbus-interface-introspectable, dbus-interface-properties) (dbus-path-emacs, dbus-interface-emacs, dbus-return-values-table): Adapt docstring. (dbus-interface-objectmanager): New defconst. (dbus-call-method, dbus-call-method-asynchronously) (dbus-send-signal, dbus-method-return-internal) (dbus-method-error-internal, dbus-register-service) (dbus-register-signal, dbus-register-method): New defuns, moved from dbusbind.c (dbus-call-method-handler, dbus-setenv) (dbus-get-all-managed-objects, dbus-managed-objects-handler): New defuns. (dbus-call-method-non-blocking): Make it an obsolete function. (dbus-unregister-object, dbus-unregister-service) (dbus-handle-event, dbus-register-property) (dbus-property-handler): Obey the new structure of `bus-registered-objects'. (dbus-introspect): Use `dbus-call-method'. Use a timeout. (dbus-get-property, dbus-set-property, dbus-get-all-properties): Use `dbus-call-method'. * dbus.texi (Version): New node. (Properties and Annotations): Mention the object manager interface. Describe dbus-get-all-managed-objects. (Type Conversion): Floating point numbers are allowed, if an anteger does not fit Emacs's integer range. (Synchronous Methods): Remove obsolete dbus-call-method-non-blocking. (Asynchronous Methods): Fix description of dbus-call-method-asynchronously. (Receiving Method Calls): Fix some minor errors. Add dbus-interface-emacs. (Signals): Describe unicast signals and the new match rules. (Alternative Buses): Add the PRIVATE optional argument to dbus-init-bus. Describe its new return value. Add dbus-setenv.
-rw-r--r--ChangeLog6
-rw-r--r--configure.in11
-rw-r--r--doc/misc/ChangeLog16
-rw-r--r--doc/misc/dbus.texi313
-rw-r--r--etc/NEWS30
-rw-r--r--lisp/ChangeLog33
-rw-r--r--lisp/net/dbus.el1065
-rw-r--r--src/ChangeLog45
-rw-r--r--src/dbusbind.c1732
9 files changed, 1797 insertions, 1454 deletions
diff --git a/ChangeLog b/ChangeLog
index 19975429260..505a447c980 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
12012-04-22 Michael Albinus <michael.albinus@gmx.de>
2
3 * configure.in (dbus_validate_bus_name, dbus_validate_path)
4 (dbus_validate_interface, dbus_validate_member): Check also for
5 these library functions
6
12012-04-22 Paul Eggert <eggert@cs.ucla.edu> 72012-04-22 Paul Eggert <eggert@cs.ucla.edu>
2 8
3 * configure.in (doug_lea_malloc): Check for __malloc_initialize_hook. 9 * configure.in (doug_lea_malloc): Check for __malloc_initialize_hook.
diff --git a/configure.in b/configure.in
index e4e11bdf7b5..4c6f4e537c6 100644
--- a/configure.in
+++ b/configure.in
@@ -2079,8 +2079,7 @@ if test "${HAVE_GTK}" = "yes"; then
2079fi 2079fi
2080 2080
2081dnl D-Bus has been tested under GNU/Linux only. Must be adapted for 2081dnl D-Bus has been tested under GNU/Linux only. Must be adapted for
2082dnl other platforms. Support for higher D-Bus versions than 1.0 is 2082dnl other platforms.
2083dnl also not configured.
2084HAVE_DBUS=no 2083HAVE_DBUS=no
2085DBUS_OBJ= 2084DBUS_OBJ=
2086if test "${with_dbus}" = "yes"; then 2085if test "${with_dbus}" = "yes"; then
@@ -2088,7 +2087,13 @@ if test "${with_dbus}" = "yes"; then
2088 if test "$HAVE_DBUS" = yes; then 2087 if test "$HAVE_DBUS" = yes; then
2089 LIBS="$LIBS $DBUS_LIBS" 2088 LIBS="$LIBS $DBUS_LIBS"
2090 AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if using D-Bus.]) 2089 AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if using D-Bus.])
2091 AC_CHECK_FUNCS([dbus_watch_get_unix_fd]) 2090 dnl dbus_watch_get_unix_fd has been introduced in D-Bus 1.1.1.
2091 dnl dbus_validate_* have been introduced in D-Bus 1.5.12.
2092 AC_CHECK_FUNCS(dbus_watch_get_unix_fd \
2093 dbus_validate_bus_name \
2094 dbus_validate_path \
2095 dbus_validate_interface \
2096 dbus_validate_member)
2092 DBUS_OBJ=dbusbind.o 2097 DBUS_OBJ=dbusbind.o
2093 fi 2098 fi
2094fi 2099fi
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog
index 14f389044bb..834a8f2c47f 100644
--- a/doc/misc/ChangeLog
+++ b/doc/misc/ChangeLog
@@ -1,3 +1,19 @@
12012-04-22 Michael Albinus <michael.albinus@gmx.de>
2
3 * dbus.texi (Version): New node.
4 (Properties and Annotations): Mention the object manager
5 interface. Describe dbus-get-all-managed-objects.
6 (Type Conversion): Floating point numbers are allowed, if an
7 anteger does not fit Emacs's integer range.
8 (Synchronous Methods): Remove obsolete dbus-call-method-non-blocking.
9 (Asynchronous Methods): Fix description of
10 dbus-call-method-asynchronously.
11 (Receiving Method Calls): Fix some minor errors. Add
12 dbus-interface-emacs.
13 (Signals): Describe unicast signals and the new match rules.
14 (Alternative Buses): Add the PRIVATE optional argument to
15 dbus-init-bus. Describe its new return value. Add dbus-setenv.
16
12012-04-20 Glenn Morris <rgm@gnu.org> 172012-04-20 Glenn Morris <rgm@gnu.org>
2 18
3 * faq.texi (New in Emacs 24): New section. 19 * faq.texi (New in Emacs 24): New section.
diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi
index 204afe7056e..e99e20b9aa0 100644
--- a/doc/misc/dbus.texi
+++ b/doc/misc/dbus.texi
@@ -53,7 +53,7 @@ another. An overview of D-Bus can be found at
53* Asynchronous Methods:: Calling methods non-blocking. 53* Asynchronous Methods:: Calling methods non-blocking.
54* Receiving Method Calls:: Offering own methods. 54* Receiving Method Calls:: Offering own methods.
55* Signals:: Sending and receiving signals. 55* Signals:: Sending and receiving signals.
56* Alternative Buses:: Alternative buses. 56* Alternative Buses:: Alternative buses and environments.
57* Errors and Events:: Errors and events. 57* Errors and Events:: Errors and events.
58* Index:: Index including concepts, functions, variables. 58* Index:: Index including concepts, functions, variables.
59 59
@@ -116,6 +116,7 @@ name could be @samp{org.gnu.Emacs.TextEditor} or
116@cindex inspection 116@cindex inspection
117 117
118@menu 118@menu
119* Version:: Determining the D-Bus version.
119* Bus names:: Discovering D-Bus names. 120* Bus names:: Discovering D-Bus names.
120* Introspection:: Knowing the details of D-Bus services. 121* Introspection:: Knowing the details of D-Bus services.
121* Nodes and Interfaces:: Detecting object paths and interfaces. 122* Nodes and Interfaces:: Detecting object paths and interfaces.
@@ -125,6 +126,25 @@ name could be @samp{org.gnu.Emacs.TextEditor} or
125@end menu 126@end menu
126 127
127 128
129@node Version
130@section D-Bus version.
131
132D-Bus has evolved over the years. New features have been added with
133new D-Bus versions. There are two variables, which allow to determine
134the used D-Bus version.
135
136@defvar dbus-compiled-version
137This variable, a string, determines the version of D-Bus Emacs is
138compiled against. If it cannot be determined the value is @code{nil}.
139@end defvar
140
141@defvar dbus-runtime-version
142The other D-Bus version to be checked is the version of D-Bus Emacs
143runs with. This string can be different from @code{dbus-compiled-version}.
144It is also @code{nil}, if it cannot be determined at runtime.
145@end defvar
146
147
128@node Bus names 148@node Bus names
129@section Bus names. 149@section Bus names.
130 150
@@ -149,7 +169,6 @@ activatable service names at all. Example:
149(member "org.gnome.evince.Daemon" 169(member "org.gnome.evince.Daemon"
150 (dbus-list-activatable-names :session)) 170 (dbus-list-activatable-names :session))
151@end lisp 171@end lisp
152
153@end defun 172@end defun
154 173
155@defun dbus-list-names bus 174@defun dbus-list-names bus
@@ -637,6 +656,12 @@ Interfaces can have properties. These can be exposed via the
637That is, properties can be retrieved and changed during lifetime of an 656That is, properties can be retrieved and changed during lifetime of an
638element. 657element.
639 658
659A generalized interface is
660@samp{org.freedesktop.DBus.Objectmanager}@footnote{See
661@uref{http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager}},
662which returns objects, their interfaces and properties for a given
663service in just one call.
664
640Annotations, on the other hand, are static values for an element. 665Annotations, on the other hand, are static values for an element.
641Often, they are used to instruct generators, how to generate code from 666Often, they are used to instruct generators, how to generate code from
642the interface for a given language binding. 667the interface for a given language binding.
@@ -732,6 +757,61 @@ If there are no properties, @code{nil} is returned. Example:
732@end lisp 757@end lisp
733@end defun 758@end defun
734 759
760@defun dbus-get-all-managed-objects bus service path
761This functions returns all objects at @var{bus}, @var{service},
762@var{path}, and the children of @var{path}. The result is a list of
763objects. Every object is a cons of an existing path name, and the
764list of available interface objects. An interface object is another
765cons, which car is the interface name, and the cdr is the list of
766properties as returned by @code{dbus-get-all-properties} for that path
767and interface. Example:
768
769@lisp
770(dbus-get-all-managed-objects
771 :session "org.gnome.SettingsDaemon" "/")
772
773@result{} (("/org/gnome/SettingsDaemon/MediaKeys"
774 ("org.gnome.SettingsDaemon.MediaKeys")
775 ("org.freedesktop.DBus.Peer")
776 ("org.freedesktop.DBus.Introspectable")
777 ("org.freedesktop.DBus.Properties")
778 ("org.freedesktop.DBus.ObjectManager"))
779 ("/org/gnome/SettingsDaemon/Power"
780 ("org.gnome.SettingsDaemon.Power.Keyboard")
781 ("org.gnome.SettingsDaemon.Power.Screen")
782 ("org.gnome.SettingsDaemon.Power"
783 ("Icon" . ". GThemedIcon battery-full-charged-symbolic ")
784 ("Tooltip" . "Laptop battery is charged"))
785 ("org.freedesktop.DBus.Peer")
786 ("org.freedesktop.DBus.Introspectable")
787 ("org.freedesktop.DBus.Properties")
788 ("org.freedesktop.DBus.ObjectManager"))
789 @dots{})
790@end lisp
791
792If possible, @samp{org.freedesktop.DBus.ObjectManager.GetManagedObjects}
793is used for retrieving the information. Otherwise, the information
794is collected via @samp{org.freedesktop.DBus.Introspectable.Introspect}
795and @samp{org.freedesktop.DBus.Properties.GetAll}, which is slow.
796
797An overview of all existing object paths, their interfaces and
798properties could be retrieved by the following code:
799
800@lisp
801(with-current-buffer (switch-to-buffer "*objectmanager*")
802 (erase-buffer)
803 (let (result)
804 (dolist (service (dbus-list-known-names :session) result)
805 (message "%s" service)
806 (add-to-list
807 'result
808 (cons service
809 (dbus-get-all-managed-objects :session service "/"))))
810 (insert (message "%s" (pp result)))
811 (redisplay t)))
812@end lisp
813@end defun
814
735@defun dbus-introspect-get-annotation-names bus service path interface &optional name 815@defun dbus-introspect-get-annotation-names bus service path interface &optional name
736Return a list of all annotation names as list of strings. If 816Return a list of all annotation names as list of strings. If
737@var{name} is @code{nil}, the annotations are children of 817@var{name} is @code{nil}, the annotations are children of
@@ -928,6 +1008,10 @@ represented outside this range are stripped of. For example,
928@code{:byte ?x} is equal to @code{:byte ?\M-x}, but it is not equal to 1008@code{:byte ?x} is equal to @code{:byte ?\M-x}, but it is not equal to
929@code{:byte ?\C-x} or @code{:byte ?\M-\C-x}. 1009@code{:byte ?\C-x} or @code{:byte ?\M-\C-x}.
930 1010
1011Signed and unsigned integer D-Bus types expect a corresponding integer
1012value. If the value does not fit Emacs's integer range, it is also
1013possible to use an equivalent floating point number.
1014
931A D-Bus compound type is always represented as a list. The @sc{car} 1015A D-Bus compound type is always represented as a list. The @sc{car}
932of this list can be the type symbol @code{:array}, @code{:variant}, 1016of this list can be the type symbol @code{:array}, @code{:variant},
933@code{:struct} or @code{:dict-entry}, which would result in a 1017@code{:struct} or @code{:dict-entry}, which would result in a
@@ -1182,24 +1266,6 @@ emulate the @code{lshal} command on GNU/Linux systems:
1182@end lisp 1266@end lisp
1183@end defun 1267@end defun
1184 1268
1185@defun dbus-call-method-non-blocking bus service path interface method &optional :timeout timeout &rest args
1186Call @var{method} on the D-Bus @var{bus}, but don't block the event queue.
1187This is necessary for communicating to registered D-Bus methods,
1188which are running in the same Emacs process.
1189
1190The arguments are the same as in @code{dbus-call-method}. Example:
1191
1192@lisp
1193(dbus-call-method-non-blocking
1194 :system "org.freedesktop.Hal"
1195 "/org/freedesktop/Hal/devices/computer"
1196 "org.freedesktop.Hal.Device" "GetPropertyString"
1197 "system.kernel.machine")
1198
1199@result{} "i686"
1200@end lisp
1201@end defun
1202
1203 1269
1204@node Asynchronous Methods 1270@node Asynchronous Methods
1205@chapter Calling methods non-blocking. 1271@chapter Calling methods non-blocking.
@@ -1229,7 +1295,7 @@ All other arguments args are passed to @var{method} as arguments.
1229They are converted into D-Bus types as described in @ref{Type 1295They are converted into D-Bus types as described in @ref{Type
1230Conversion}. 1296Conversion}.
1231 1297
1232Unless @var{handler} is @code{nil}, the function returns a key into 1298If @var{handler} is a Lisp function, the function returns a key into
1233the hash table @code{dbus-registered-objects-table}. The 1299the hash table @code{dbus-registered-objects-table}. The
1234corresponding entry in the hash table is removed, when the return 1300corresponding entry in the hash table is removed, when the return
1235message has been arrived, and @var{handler} is called. Example: 1301message has been arrived, and @var{handler} is called. Example:
@@ -1241,7 +1307,7 @@ message has been arrived, and @var{handler} is called. Example:
1241 "org.freedesktop.Hal.Device" "GetPropertyString" 'message 1307 "org.freedesktop.Hal.Device" "GetPropertyString" 'message
1242 "system.kernel.machine") 1308 "system.kernel.machine")
1243 1309
1244@result{} (:system 2) 1310@result{} (:serial :system 2)
1245 1311
1246@print{} i686 1312@print{} i686
1247@end lisp 1313@end lisp
@@ -1323,19 +1389,21 @@ implementation of an interface of a well known service, like
1323 1389
1324It could be also an implementation of an own interface. In this case, 1390It could be also an implementation of an own interface. In this case,
1325the service name must be @samp{org.gnu.Emacs}. The object path shall 1391the service name must be @samp{org.gnu.Emacs}. The object path shall
1326begin with @samp{/org/gnu/Emacs/@strong{Application}/}, and the 1392begin with @samp{/org/gnu/Emacs/@strong{Application}}, and the
1327interface name shall be @code{org.gnu.Emacs.@strong{Application}}. 1393interface name shall be @code{org.gnu.Emacs.@strong{Application}}.
1328@samp{@strong{Application}} is the name of the application which 1394@samp{@strong{Application}} is the name of the application which
1329provides the interface. 1395provides the interface.
1330 1396
1331@deffn Constant dbus-service-emacs 1397@deffn Constant dbus-service-emacs
1332The well known service name of Emacs. 1398The well known service name @samp{org.gnu.Emacs} of Emacs.
1333@end deffn 1399@end deffn
1334 1400
1335@deffn Constant dbus-path-emacs 1401@deffn Constant dbus-path-emacs
1336The object path head "/org/gnu/Emacs" used by Emacs. All object 1402The object path namespace @samp{/org/gnu/Emacs} used by Emacs.
1337paths, used by offered methods or signals, shall start with this 1403@end deffn
1338string. 1404
1405@deffn Constant dbus-interface-emacs
1406The interface namespace @code{org.gnu.Emacs} used by Emacs.
1339@end deffn 1407@end deffn
1340 1408
1341@defun dbus-register-method bus service path interface method handler dont-register-service 1409@defun dbus-register-method bus service path interface method handler dont-register-service
@@ -1400,7 +1468,7 @@ registration for @var{method}. Example:
1400 "org.freedesktop.TextEditor" "OpenFile" 1468 "org.freedesktop.TextEditor" "OpenFile"
1401 'my-dbus-method-handler) 1469 'my-dbus-method-handler)
1402 1470
1403@result{} ((:session "org.freedesktop.TextEditor" "OpenFile") 1471@result{} ((:method :session "org.freedesktop.TextEditor" "OpenFile")
1404 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" 1472 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
1405 my-dbus-method-handler)) 1473 my-dbus-method-handler))
1406@end lisp 1474@end lisp
@@ -1497,14 +1565,14 @@ clients from discovering the still incomplete interface.
1497 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" 1565 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
1498 "org.freedesktop.TextEditor" "name" :read "GNU Emacs") 1566 "org.freedesktop.TextEditor" "name" :read "GNU Emacs")
1499 1567
1500@result{} ((:session "org.freedesktop.TextEditor" "name") 1568@result{} ((:property :session "org.freedesktop.TextEditor" "name")
1501 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor")) 1569 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"))
1502 1570
1503(dbus-register-property 1571(dbus-register-property
1504 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor" 1572 :session "org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"
1505 "org.freedesktop.TextEditor" "version" :readwrite emacs-version t) 1573 "org.freedesktop.TextEditor" "version" :readwrite emacs-version t)
1506 1574
1507@result{} ((:session "org.freedesktop.TextEditor" "version") 1575@result{} ((:property :session "org.freedesktop.TextEditor" "version")
1508 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor")) 1576 ("org.freedesktop.TextEditor" "/org/freedesktop/TextEditor"))
1509@end lisp 1577@end lisp
1510 1578
@@ -1569,8 +1637,8 @@ to the service from D-Bus.
1569@chapter Sending and receiving signals. 1637@chapter Sending and receiving signals.
1570@cindex signals 1638@cindex signals
1571 1639
1572Signals are broadcast messages. They carry input parameters, which 1640Signals are one way messages. They carry input parameters, which are
1573are received by all objects which have registered for such a signal. 1641received by all objects which have registered for such a signal.
1574 1642
1575@defun dbus-send-signal bus service path interface signal &rest args 1643@defun dbus-send-signal bus service path interface signal &rest args
1576This function is similar to @code{dbus-call-method}. The difference 1644This function is similar to @code{dbus-call-method}. The difference
@@ -1580,10 +1648,14 @@ The function emits @var{signal} on the D-Bus @var{bus}. @var{bus} is
1580either the symbol @code{:system} or the symbol @code{:session}. It 1648either the symbol @code{:system} or the symbol @code{:session}. It
1581doesn't matter whether another object has registered for @var{signal}. 1649doesn't matter whether another object has registered for @var{signal}.
1582 1650
1583@var{service} is the D-Bus service name of the object the signal is 1651Signals can be unicast or broadcast messages. For broadcast messages,
1584emitted from. @var{path} is the corresponding D-Bus object path, 1652@var{service} must be @code{nil}. Otherwise, @var{service} is the
1585@var{service} is registered at. @var{interface} is an interface 1653D-Bus service name the signal is sent to as unicast
1586offered by @var{service}. It must provide @var{signal}. 1654message.@footnote{For backward compatibility, a broadcast message is
1655also emitted if @var{service} is the known or unique name Emacs is
1656registered at D-Bus @var{bus}.} @var{path} is the D-Bus object path
1657@var{signal} is sent from. @var{interface} is an interface available
1658at @var{path}. It must provide @var{signal}.
1587 1659
1588All other arguments args are passed to @var{signal} as arguments. 1660All other arguments args are passed to @var{signal} as arguments.
1589They are converted into D-Bus types as described in @ref{Type 1661They are converted into D-Bus types as described in @ref{Type
@@ -1591,15 +1663,15 @@ Conversion}. Example:
1591 1663
1592@lisp 1664@lisp
1593(dbus-send-signal 1665(dbus-send-signal
1594 :session dbus-service-emacs dbus-path-emacs 1666 :session nil dbus-path-emacs
1595 (concat dbus-service-emacs ".FileManager") "FileModified" 1667 (concat dbus-interface-emacs ".FileManager") "FileModified"
1596 "/home/albinus/.emacs") 1668 "/home/albinus/.emacs")
1597@end lisp 1669@end lisp
1598@end defun 1670@end defun
1599 1671
1600@defun dbus-register-signal bus service path interface signal handler &rest args 1672@defun dbus-register-signal bus service path interface signal handler &rest args
1601With this function, an application registers for @var{signal} on the 1673With this function, an application registers for a signal on the D-Bus
1602D-Bus @var{bus}. 1674@var{bus}.
1603 1675
1604@var{bus} is either the symbol @code{:system} or the symbol 1676@var{bus} is either the symbol @code{:system} or the symbol
1605@code{:session}. 1677@code{:session}.
@@ -1611,24 +1683,46 @@ unique name of the object, owning @var{service} at registration time.
1611When the corresponding D-Bus object disappears, signals won't be 1683When the corresponding D-Bus object disappears, signals won't be
1612received any longer. 1684received any longer.
1613 1685
1614When @var{service} is @code{nil}, related signals from all D-Bus
1615objects shall be accepted.
1616
1617@var{path} is the corresponding D-Bus object path, @var{service} is 1686@var{path} is the corresponding D-Bus object path, @var{service} is
1618registered at. It can also be @code{nil} if the path name of incoming 1687registered at. @var{interface} is an interface offered by
1619signals shall not be checked. 1688@var{service}. It must provide @var{signal}.
1620 1689
1621@var{interface} is an interface offered by @var{service}. It must 1690@var{service}, @var{path}, @var{interface} and @var{signal} can be
1622provide @var{signal}. 1691@code{nil}. This is interpreted as a wildcard for the respective
1692argument.
1623 1693
1624@var{handler} is a Lisp function to be called when the @var{signal} is 1694@var{handler} is a Lisp function to be called when the @var{signal} is
1625received. It must accept as arguments the output parameters 1695received. It must accept as arguments the output parameters
1626@var{signal} is sending. 1696@var{signal} is sending.
1627 1697
1628All other arguments @var{args}, if specified, must be strings. They 1698The remaining arguments @var{args} can be keywords or keyword string
1629stand for the respective arguments of @var{signal} in their order, and 1699pairs.@footnote{For backward compatibility, the arguments @var{args}
1630are used for filtering as well. A @code{nil} argument might be used 1700can also be just strings. They stand for the respective arguments of
1631to preserve the order. 1701@var{signal} in their order, and are used for filtering as well. A
1702@code{nil} argument might be used to preserve the order.} The meaning
1703is as follows:
1704
1705@itemize
1706@item @code{:argN} @var{string}:@*
1707@code{:pathN} @var{string}:@*
1708This stands for the Nth argument of the signal. @code{:pathN}
1709arguments can be used for object path wildcard matches as specified by
1710D-Bus, whilest an @code{:argN} argument requires an exact match.
1711
1712@item @code{:arg-namespace} @var{string}:@*
1713Register for the signals, which first argument defines the service or
1714interface namespace @var{string}.
1715
1716@item @code{:path-namespace} @var{string}:@*
1717Register for the object path namespace @var{string}. All signals sent
1718from an object path, which has @var{string} as the preceding string,
1719are matched. This requires @var{path} to be @code{nil}.
1720
1721@item @code{:eavesdrop}:@*
1722Register for unicast signals which are not directed to the D-Bus
1723object Emacs is registered at D-Bus BUS, if the security policy of BUS
1724allows this. Otherwise, this argument is ignored.
1725@end itemize
1632 1726
1633@code{dbus-register-signal} returns a Lisp object, which can be used 1727@code{dbus-register-signal} returns a Lisp object, which can be used
1634as argument in @code{dbus-unregister-object} for removing the 1728as argument in @code{dbus-unregister-object} for removing the
@@ -1645,7 +1739,7 @@ registration for @var{signal}. Example:
1645 "org.freedesktop.Hal.Manager" "DeviceAdded" 1739 "org.freedesktop.Hal.Manager" "DeviceAdded"
1646 'my-dbus-signal-handler) 1740 'my-dbus-signal-handler)
1647 1741
1648@result{} ((:system "org.freedesktop.Hal.Manager" "DeviceAdded") 1742@result{} ((:signal :system "org.freedesktop.Hal.Manager" "DeviceAdded")
1649 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" 1743 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
1650 my-signal-handler)) 1744 my-signal-handler))
1651@end lisp 1745@end lisp
@@ -1657,23 +1751,36 @@ The callback function @code{my-dbus-signal-handler} must define one
1657single string argument therefore. Plugging an USB device to your 1751single string argument therefore. Plugging an USB device to your
1658machine, when registered for signal @samp{DeviceAdded}, will show you 1752machine, when registered for signal @samp{DeviceAdded}, will show you
1659which objects the GNU/Linux @code{hal} daemon adds. 1753which objects the GNU/Linux @code{hal} daemon adds.
1754
1755Some of the match rules have been added to a later version of D-Bus.
1756In order to test the availability of such features, you could register
1757for a dummy signal, and check the result:
1758
1759@lisp
1760(dbus-ignore-errors
1761 (dbus-register-signal
1762 :system nil nil nil nil 'ignore :path-namespace "/invalid/path"))
1763
1764@result{} nil
1765@end lisp
1660@end defun 1766@end defun
1661 1767
1662 1768
1663@node Alternative Buses 1769@node Alternative Buses
1664@chapter Alternative buses. 1770@chapter Alternative buses and environments.
1665@cindex bus names 1771@cindex bus names
1666@cindex UNIX domain socket 1772@cindex UNIX domain socket
1773@cindex TCP/IP socket
1667 1774
1668Until now, we have spoken about the system and the session buses, 1775Until now, we have spoken about the system and the session buses,
1669which are the default buses to be connected to. However, it is 1776which are the default buses to be connected to. However, it is
1670possible to connect to any bus, from which the address is known. This 1777possible to connect to any bus, from which the address is known. This
1671is a UNIX domain socket. Everywhere, where a @var{bus} is mentioned 1778is a UNIX domain or TCP/IP socket. Everywhere, where a @var{bus} is
1672as argument of a function (the symbol @code{:system} or the symbol 1779mentioned as argument of a function (the symbol @code{:system} or the
1673@code{:session}), this address can be used instead. The connection to 1780symbol @code{:session}), this address can be used instead. The
1674this bus must be initialized first. 1781connection to this bus must be initialized first.
1675 1782
1676@defun dbus-init-bus bus 1783@defun dbus-init-bus bus &optional private
1677Establish the connection to D-Bus @var{bus}. 1784Establish the connection to D-Bus @var{bus}.
1678 1785
1679@var{bus} can be either the symbol @code{:system} or the symbol 1786@var{bus} can be either the symbol @code{:system} or the symbol
@@ -1682,30 +1789,90 @@ corresponding bus. For the system and session buses, this function
1682is called when loading @file{dbus.el}, there is no need to call it 1789is called when loading @file{dbus.el}, there is no need to call it
1683again. 1790again.
1684 1791
1685Example: You open another session bus in a terminal window on your host: 1792The function returns a number, which counts the connections this Emacs
1793session has established to the @var{bus} under the same unique name
1794(see @code{dbus-get-unique-name}). It depends on the libraries Emacs
1795is linked with, and on the environment Emacs is running. For example,
1796if Emacs is linked with the gtk toolkit, and it runs in a GTK-aware
1797environment like Gnome, another connection might already be
1798established.
1686 1799
1687@example 1800When @var{private} is non-@code{nil}, a new connection is established
1688# eval `dbus-launch --auto-syntax` 1801instead of reusing an existing one. It results in a new unique name
1689# echo $DBUS_SESSION_BUS_ADDRESS 1802at the bus. This can be used, if it is necessary to distinguish from
1803another connection used in the same Emacs process, like the one
1804established by GTK+. It should be used with care for at least the
1805@code{:system} and @code{:session} buses, because other Emacs Lisp
1806packages might already use this connection to those buses.
1690 1807
1691@print{} unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e 1808Example: You initialize a connection to the AT-SPI bus on your host:
1692@end example
1693
1694In Emacs, you can access to this bus via its address:
1695 1809
1696@lisp 1810@lisp
1697(setq my-bus 1811(setq my-bus
1698 "unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e") 1812 (dbus-call-method
1813 :session "org.a11y.Bus" "/org/a11y/bus"
1814 "org.a11y.Bus" "GetAddress"))
1699 1815
1700@result{} "unix:abstract=/tmp/dbus-JoFtAVG92w,guid=2f320a1ebe50b7ef58e" 1816@result{} "unix:abstract=/tmp/dbus-2yzWHOCdSD,guid=a490dd26625870ca1298b6e10000fd7f"
1701 1817
1818;; If Emacs is built with gtk support, and you run in a GTK enabled
1819;; environment (like a GNOME session), the initialization reuses the
1820;; connection established by GTK's atk bindings.
1702(dbus-init-bus my-bus) 1821(dbus-init-bus my-bus)
1703 1822
1704@result{} nil 1823@result{} 2
1705 1824
1706(dbus-get-unique-name my-bus) 1825(dbus-get-unique-name my-bus)
1707 1826
1708@result{} ":1.0" 1827@result{} ":1.19"
1828
1829;; Open a new connection to the same bus. This obsoletes the
1830;; previous one.
1831(dbus-init-bus my-bus 'private)
1832
1833@result{} 1
1834
1835(dbus-get-unique-name my-bus)
1836
1837@result{} ":1.20"
1838@end lisp
1839
1840D-Bus addresses can specify different transport. A possible address
1841could be based on TCP/IP sockets, see next example. However, it
1842depends on the bus daemon configuration, which transport is supported.
1843@end defun
1844
1845@defun dbus-setenv bus variable value
1846Set the value of the @var{bus} environment variable @var{variable} to
1847@var{value}.
1848
1849@var{bus} is either a Lisp symbol, @code{:system} or @code{:session},
1850or a string denoting the bus address. Both @var{variable} and
1851@var{value} should be strings.
1852
1853Normally, services inherit the environment of the bus daemon. This
1854function adds to or modifies that environment when activating services.
1855
1856Some bus instances, such as @code{:system}, may disable setting the
1857environment. In such cases, or if this feature is not available in
1858older D-Bus versions, a @code{dbus-error} error is raised.
1859
1860As an example, it might be desirable to start X11 enabled services on
1861a remote host's bus on the same X11 server the local Emacs is
1862running. This could be achieved by
1863
1864@lisp
1865(setq my-bus "unix:host=example.gnu.org,port=4711")
1866
1867@result{} "unix:host=example.gnu.org,port=4711"
1868
1869(dbus-init-bus my-bus)
1870
1871@result{} 1
1872
1873(dbus-setenv my-bus "DISPLAY" (getenv "DISPLAY"))
1874
1875@result{} nil
1709@end lisp 1876@end lisp
1710@end defun 1877@end defun
1711 1878
@@ -1723,8 +1890,8 @@ If this variable is non-@code{nil}, D-Bus specific debug messages are raised.
1723@end defvar 1890@end defvar
1724 1891
1725Input parameters of @code{dbus-call-method}, 1892Input parameters of @code{dbus-call-method},
1726@code{dbus-call-method-non-blocking}, 1893@code{dbus-call-method-asynchronously}, @code{dbus-send-signal},
1727@code{dbus-call-method-asynchronously}, and 1894@code{dbus-register-method}, @code{dbus-register-property} and
1728@code{dbus-register-signal} are checked for correct D-Bus types. If 1895@code{dbus-register-signal} are checked for correct D-Bus types. If
1729there is a type mismatch, the Lisp error @code{wrong-type-argument} 1896there is a type mismatch, the Lisp error @code{wrong-type-argument}
1730@code{D-Bus ARG} is raised. 1897@code{D-Bus ARG} is raised.
@@ -1825,7 +1992,7 @@ Example:
1825 1992
1826@lisp 1993@lisp
1827(defun my-dbus-event-error-handler (event error) 1994(defun my-dbus-event-error-handler (event error)
1828 (when (string-equal (concat dbus-service-emacs ".FileManager") 1995 (when (string-equal (concat dbus-interface-emacs ".FileManager")
1829 (dbus-event-interface-name event)) 1996 (dbus-event-interface-name event))
1830 (message "my-dbus-event-error-handler: %S %S" event error) 1997 (message "my-dbus-event-error-handler: %S %S" event error)
1831 (signal 'file-error (cdr error)))) 1998 (signal 'file-error (cdr error))))
diff --git a/etc/NEWS b/etc/NEWS
index 298a87c1f08..3b53f9df97a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -91,6 +91,36 @@ closing brackets to be aligned with the line of the opening bracket.
91 91
92** which-function-mode now applies to all applicable major modes by default. 92** which-function-mode now applies to all applicable major modes by default.
93 93
94** D-Bus
95
96+++
97*** New variables `dbus-compiled-version' and `dbus-runtime-version'.
98
99+++
100*** The D-Bus object manager interface is implemented.
101
102+++
103*** Variables of type :(u)int32 and :(u)int64 accept floating points,
104if their value does not fit into Emacs's integer range.
105
106+++
107*** The function `dbus-call-method' works non-blocking now, it can be
108interrupted by C-g. `dbus-call-method-non-blocking' is obsolete.
109
110+++
111*** Signals can be sent also as unicast message.
112
113+++
114*** The argument list of `dbus-register-signal' has been extended,
115according to the new match rule types of D-Bus. See the manual for
116details.
117
118+++
119*** `dbus-init-bus' supports private connections.
120
121+++
122*** There is a new function `dbus-setenv'.
123
94** Obsolete packages: 124** Obsolete packages:
95 125
96*** mailpost.el 126*** mailpost.el
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 14a83de342a..334e34bb712 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,36 @@
12012-04-22 Michael Albinus <michael.albinus@gmx.de>
2
3 Move functions from C to Lisp. Make non-blocking method calls
4 the default. Implement further D-Bus standard interfaces.
5
6 * net/dbus.el (dbus-message-internal): Declare function. Remove
7 unneeded function declarations.
8 (defvar dbus-message-type-invalid, dbus-message-type-method-call)
9 (dbus-message-type-method-return, dbus-message-type-error)
10 (dbus-message-type-signal): Declare variables. Remove local
11 definitions.
12 (dbus-interface-dbus, dbus-interface-peer)
13 (dbus-interface-introspectable, dbus-interface-properties)
14 (dbus-path-emacs, dbus-interface-emacs, dbus-return-values-table):
15 Adapt docstring.
16 (dbus-interface-objectmanager): New defconst.
17 (dbus-call-method, dbus-call-method-asynchronously)
18 (dbus-send-signal, dbus-method-return-internal)
19 (dbus-method-error-internal, dbus-register-service)
20 (dbus-register-signal, dbus-register-method): New defuns, moved
21 from dbusbind.c
22 (dbus-call-method-handler, dbus-setenv)
23 (dbus-get-all-managed-objects, dbus-managed-objects-handler): New
24 defuns.
25 (dbus-call-method-non-blocking): Make it an obsolete function.
26 (dbus-unregister-object, dbus-unregister-service)
27 (dbus-handle-event, dbus-register-property)
28 (dbus-property-handler): Obey the new structure of
29 `bus-registered-objects'.
30 (dbus-introspect): Use `dbus-call-method'. Use a timeout.
31 (dbus-get-property, dbus-set-property, dbus-get-all-properties):
32 Use `dbus-call-method'.
33
12012-04-22 Chong Yidong <cyd@gnu.org> 342012-04-22 Chong Yidong <cyd@gnu.org>
2 35
3 * cus-edit.el (custom-commands, custom-reset-menu) 36 * cus-edit.el (custom-commands, custom-reset-menu)
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index e3144a53fab..ee2bdecb1ac 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -28,19 +28,19 @@
28 28
29;; Low-level language bindings are implemented in src/dbusbind.c. 29;; Low-level language bindings are implemented in src/dbusbind.c.
30 30
31;; D-Bus support in the Emacs core can be disabled with configuration
32;; option "--without-dbus".
33
31;;; Code: 34;;; Code:
32 35
33;; D-Bus support in the Emacs core can be disabled with configuration 36;; Declare used subroutines and variables.
34;; option "--without-dbus". Declare used subroutines and variables. 37(declare-function dbus-message-internal "dbusbind.c")
35(declare-function dbus-call-method "dbusbind.c")
36(declare-function dbus-call-method-asynchronously "dbusbind.c")
37(declare-function dbus-init-bus "dbusbind.c") 38(declare-function dbus-init-bus "dbusbind.c")
38(declare-function dbus-method-return-internal "dbusbind.c") 39(defvar dbus-message-type-invalid)
39(declare-function dbus-method-error-internal "dbusbind.c") 40(defvar dbus-message-type-method-call)
40(declare-function dbus-register-service "dbusbind.c") 41(defvar dbus-message-type-method-return)
41(declare-function dbus-register-signal "dbusbind.c") 42(defvar dbus-message-type-error)
42(declare-function dbus-register-method "dbusbind.c") 43(defvar dbus-message-type-signal)
43(declare-function dbus-send-signal "dbusbind.c")
44(defvar dbus-debug) 44(defvar dbus-debug)
45(defvar dbus-registered-objects-table) 45(defvar dbus-registered-objects-table)
46 46
@@ -56,39 +56,93 @@
56(defconst dbus-path-dbus "/org/freedesktop/DBus" 56(defconst dbus-path-dbus "/org/freedesktop/DBus"
57 "The object path used to talk to the bus itself.") 57 "The object path used to talk to the bus itself.")
58 58
59;; Default D-Bus interfaces.
60
59(defconst dbus-interface-dbus "org.freedesktop.DBus" 61(defconst dbus-interface-dbus "org.freedesktop.DBus"
60 "The interface exported by the object with `dbus-service-dbus' and `dbus-path-dbus'.") 62 "The interface exported by the service `dbus-service-dbus'.")
61 63
62(defconst dbus-interface-peer (concat dbus-interface-dbus ".Peer") 64(defconst dbus-interface-peer (concat dbus-interface-dbus ".Peer")
63 "The interface for peer objects.") 65 "The interface for peer objects.
66See URL `http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-peer'.")
67
68;; <interface name="org.freedesktop.DBus.Peer">
69;; <method name="Ping">
70;; </method>
71;; <method name="GetMachineId">
72;; <arg name="machine_uuid" type="s" direction="out"/>
73;; </method>
74;; </interface>
64 75
65(defconst dbus-interface-introspectable 76(defconst dbus-interface-introspectable
66 (concat dbus-interface-dbus ".Introspectable") 77 (concat dbus-interface-dbus ".Introspectable")
67 "The interface supported by introspectable objects.") 78 "The interface supported by introspectable objects.
79See URL `http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable'.")
68 80
69(defconst dbus-interface-properties (concat dbus-interface-dbus ".Properties") 81;; <interface name="org.freedesktop.DBus.Introspectable">
70 "The interface for property objects.") 82;; <method name="Introspect">
83;; <arg name="data" type="s" direction="out"/>
84;; </method>
85;; </interface>
71 86
87(defconst dbus-interface-properties (concat dbus-interface-dbus ".Properties")
88 "The interface for property objects.
89See URL `http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties'.")
90
91;; <interface name="org.freedesktop.DBus.Properties">
92;; <method name="Get">
93;; <arg name="interface" type="s" direction="in"/>
94;; <arg name="propname" type="s" direction="in"/>
95;; <arg name="value" type="v" direction="out"/>
96;; </method>
97;; <method name="Set">
98;; <arg name="interface" type="s" direction="in"/>
99;; <arg name="propname" type="s" direction="in"/>
100;; <arg name="value" type="v" direction="in"/>
101;; </method>
102;; <method name="GetAll">
103;; <arg name="interface" type="s" direction="in"/>
104;; <arg name="props" type="a{sv}" direction="out"/>
105;; </method>
106;; <signal name="PropertiesChanged">
107;; <arg name="interface" type="s"/>
108;; <arg name="changed_properties" type="a{sv}"/>
109;; <arg name="invalidated_properties" type="as"/>
110;; </signal>
111;; </interface>
112
113(defconst dbus-interface-objectmanager
114 (concat dbus-interface-dbus ".ObjectManager")
115 "The object manager interface.
116See URL `http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager'.")
117
118;; <interface name="org.freedesktop.DBus.ObjectManager">
119;; <method name="GetManagedObjects">
120;; <arg name="object_paths_interfaces_and_properties"
121;; type="a{oa{sa{sv}}}" direction="out"/>
122;; </method>
123;; <signal name="InterfacesAdded">
124;; <arg name="object_path" type="o"/>
125;; <arg name="interfaces_and_properties" type="a{sa{sv}}"/>
126;; </signal>
127;; <signal name="InterfacesRemoved">
128;; <arg name="object_path" type="o"/>
129;; <arg name="interfaces" type="as"/>
130;; </signal>
131;; </interface>
132
133;; Emacs defaults.
72(defconst dbus-service-emacs "org.gnu.Emacs" 134(defconst dbus-service-emacs "org.gnu.Emacs"
73 "The well known service name of Emacs.") 135 "The well known service name of Emacs.")
74 136
75(defconst dbus-path-emacs "/org/gnu/Emacs" 137(defconst dbus-path-emacs "/org/gnu/Emacs"
76 "The object path head used by Emacs.") 138 "The object path namespace used by Emacs.
139All object paths provided by the service `dbus-service-emacs'
140shall be subdirectories of this path.")
77 141
78(defconst dbus-message-type-invalid 0 142(defconst dbus-interface-emacs "org.gnu.Emacs"
79 "This value is never a valid message type.") 143 "The interface namespace used by Emacs.")
80 144
81(defconst dbus-message-type-method-call 1 145;; D-Bus constants.
82 "Message type of a method call message.")
83
84(defconst dbus-message-type-method-return 2
85 "Message type of a method return message.")
86
87(defconst dbus-message-type-error 3
88 "Message type of an error reply message.")
89
90(defconst dbus-message-type-signal 4
91 "Message type of a signal message.")
92 146
93(defmacro dbus-ignore-errors (&rest body) 147(defmacro dbus-ignore-errors (&rest body)
94 "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil. 148 "Execute BODY; signal D-Bus error when `dbus-debug' is non-nil.
@@ -105,15 +159,267 @@ Every function must accept two arguments, the event and the error variable
105caught in `condition-case' by `dbus-error'.") 159caught in `condition-case' by `dbus-error'.")
106 160
107 161
108;;; Hash table of registered functions. 162;;; Basic D-Bus message functions.
109 163
110(defvar dbus-return-values-table (make-hash-table :test 'equal) 164(defvar dbus-return-values-table (make-hash-table :test 'equal)
111 "Hash table for temporary storing arguments of reply messages. 165 "Hash table for temporary storing arguments of reply messages.
112A key in this hash table is a list (BUS SERIAL). BUS is either a 166A key in this hash table is a list (:serial BUS SERIAL), like in
113Lisp symbol, `:system' or `:session', or a string denoting the 167`dbus-registered-objects-table'. BUS is either a Lisp symbol,
114bus address. SERIAL is the serial number of the reply message. 168`:system' or `:session', or a string denoting the bus address.
115See `dbus-call-method-non-blocking-handler' and 169SERIAL is the serial number of the reply message.")
116`dbus-call-method-non-blocking'.") 170
171(defun dbus-call-method-handler (&rest args)
172 "Handler for reply messages of asynchronous D-Bus message calls.
173It calls the function stored in `dbus-registered-objects-table'.
174The result will be made available in `dbus-return-values-table'."
175 (puthash (list :serial
176 (dbus-event-bus-name last-input-event)
177 (dbus-event-serial-number last-input-event))
178 (if (= (length args) 1) (car args) args)
179 dbus-return-values-table))
180
181(defun dbus-call-method (bus service path interface method &rest args)
182 "Call METHOD on the D-Bus BUS.
183
184BUS is either a Lisp symbol, `:system' or `:session', or a string
185denoting the bus address.
186
187SERVICE is the D-Bus service name to be used. PATH is the D-Bus
188object path SERVICE is registered at. INTERFACE is an interface
189offered by SERVICE. It must provide METHOD.
190
191If the parameter `:timeout' is given, the following integer TIMEOUT
192specifies the maximum number of milliseconds the method call must
193return. The default value is 25,000. If the method call doesn't
194return in time, a D-Bus error is raised.
195
196All other arguments ARGS are passed to METHOD as arguments. They are
197converted into D-Bus types via the following rules:
198
199 t and nil => DBUS_TYPE_BOOLEAN
200 number => DBUS_TYPE_UINT32
201 integer => DBUS_TYPE_INT32
202 float => DBUS_TYPE_DOUBLE
203 string => DBUS_TYPE_STRING
204 list => DBUS_TYPE_ARRAY
205
206All arguments can be preceded by a type symbol. For details about
207type symbols, see Info node `(dbus)Type Conversion'.
208
209`dbus-call-method' returns the resulting values of METHOD as a list of
210Lisp objects. The type conversion happens the other direction as for
211input arguments. It follows the mapping rules:
212
213 DBUS_TYPE_BOOLEAN => t or nil
214 DBUS_TYPE_BYTE => number
215 DBUS_TYPE_UINT16 => number
216 DBUS_TYPE_INT16 => integer
217 DBUS_TYPE_UINT32 => number or float
218 DBUS_TYPE_UNIX_FD => number or float
219 DBUS_TYPE_INT32 => integer or float
220 DBUS_TYPE_UINT64 => number or float
221 DBUS_TYPE_INT64 => integer or float
222 DBUS_TYPE_DOUBLE => float
223 DBUS_TYPE_STRING => string
224 DBUS_TYPE_OBJECT_PATH => string
225 DBUS_TYPE_SIGNATURE => string
226 DBUS_TYPE_ARRAY => list
227 DBUS_TYPE_VARIANT => list
228 DBUS_TYPE_STRUCT => list
229 DBUS_TYPE_DICT_ENTRY => list
230
231Example:
232
233\(dbus-call-method
234 :session \"org.gnome.seahorse\" \"/org/gnome/seahorse/keys/openpgp\"
235 \"org.gnome.seahorse.Keys\" \"GetKeyField\"
236 \"openpgp:657984B8C7A966DD\" \"simple-name\")
237
238 => (t (\"Philip R. Zimmermann\"))
239
240If the result of the METHOD call is just one value, the converted Lisp
241object is returned instead of a list containing this single Lisp object.
242
243\(dbus-call-method
244 :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/devices/computer\"
245 \"org.freedesktop.Hal.Device\" \"GetPropertyString\"
246 \"system.kernel.machine\")
247
248 => \"i686\""
249
250 (or (memq bus '(:system :session)) (stringp bus)
251 (signal 'wrong-type-argument (list 'keywordp bus)))
252 (or (stringp service)
253 (signal 'wrong-type-argument (list 'stringp service)))
254 (or (stringp path)
255 (signal 'wrong-type-argument (list 'stringp path)))
256 (or (stringp interface)
257 (signal 'wrong-type-argument (list 'stringp interface)))
258 (or (stringp method)
259 (signal 'wrong-type-argument (list 'stringp method)))
260
261 (let ((timeout (plist-get args :timeout))
262 (key
263 (apply
264 'dbus-message-internal dbus-message-type-method-call
265 bus service path interface method 'dbus-call-method-handler args)))
266 ;; Wait until `dbus-call-method-handler' has put the result into
267 ;; `dbus-return-values-table'. If no timeout is given, use the
268 ;; default 25".
269 (with-timeout ((if timeout (/ timeout 1000.0) 25))
270 (while (eq (gethash key dbus-return-values-table :ignore) :ignore)
271 (read-event nil nil 0.1)))
272
273 ;; Cleanup `dbus-return-values-table'. Return the result.
274 (prog1
275 (gethash key dbus-return-values-table)
276 (remhash key dbus-return-values-table))))
277
278;; `dbus-call-method' works non-blocking now.
279(defalias 'dbus-call-method-non-blocking 'dbus-call-method)
280(make-obsolete 'dbus-call-method-non-blocking 'dbus-call-method "24.2")
281
282(defun dbus-call-method-asynchronously
283 (bus service path interface method handler &rest args)
284 "Call METHOD on the D-Bus BUS asynchronously.
285
286BUS is either a Lisp symbol, `:system' or `:session', or a string
287denoting the bus address.
288
289SERVICE is the D-Bus service name to be used. PATH is the D-Bus
290object path SERVICE is registered at. INTERFACE is an interface
291offered by SERVICE. It must provide METHOD.
292
293HANDLER is a Lisp function, which is called when the corresponding
294return message has arrived. If HANDLER is nil, no return message
295will be expected.
296
297If the parameter `:timeout' is given, the following integer TIMEOUT
298specifies the maximum number of milliseconds the method call must
299return. The default value is 25,000. If the method call doesn't
300return in time, a D-Bus error is raised.
301
302All other arguments ARGS are passed to METHOD as arguments. They are
303converted into D-Bus types via the following rules:
304
305 t and nil => DBUS_TYPE_BOOLEAN
306 number => DBUS_TYPE_UINT32
307 integer => DBUS_TYPE_INT32
308 float => DBUS_TYPE_DOUBLE
309 string => DBUS_TYPE_STRING
310 list => DBUS_TYPE_ARRAY
311
312All arguments can be preceded by a type symbol. For details about
313type symbols, see Info node `(dbus)Type Conversion'.
314
315If HANDLER is a Lisp function, the function returns a key into the
316hash table `dbus-registered-objects-table'. The corresponding entry
317in the hash table is removed, when the return message has been arrived,
318and HANDLER is called.
319
320Example:
321
322\(dbus-call-method-asynchronously
323 :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/devices/computer\"
324 \"org.freedesktop.Hal.Device\" \"GetPropertyString\" 'message
325 \"system.kernel.machine\")
326
327 => \(:serial :system 2)
328
329 -| i686"
330
331 (or (memq bus '(:system :session)) (stringp bus)
332 (signal 'wrong-type-argument (list 'keywordp bus)))
333 (or (stringp service)
334 (signal 'wrong-type-argument (list 'stringp service)))
335 (or (stringp path)
336 (signal 'wrong-type-argument (list 'stringp path)))
337 (or (stringp interface)
338 (signal 'wrong-type-argument (list 'stringp interface)))
339 (or (stringp method)
340 (signal 'wrong-type-argument (list 'stringp method)))
341 (or (null handler) (functionp handler)
342 (signal 'wrong-type-argument (list 'functionp handler)))
343
344 (apply 'dbus-message-internal dbus-message-type-method-call
345 bus service path interface method handler args))
346
347(defun dbus-send-signal (bus service path interface signal &rest args)
348 "Send signal SIGNAL on the D-Bus BUS.
349
350BUS is either a Lisp symbol, `:system' or `:session', or a string
351denoting the bus address. The signal is sent from the D-Bus object
352Emacs is registered at BUS.
353
354SERVICE is the D-Bus name SIGNAL is sent to. It can be either a known
355name or a unique name. If SERVICE is nil, the signal is sent as
356broadcast message. PATH is the D-Bus object path SIGNAL is sent from.
357INTERFACE is an interface available at PATH. It must provide signal
358SIGNAL.
359
360All other arguments ARGS are passed to SIGNAL as arguments. They are
361converted into D-Bus types via the following rules:
362
363 t and nil => DBUS_TYPE_BOOLEAN
364 number => DBUS_TYPE_UINT32
365 integer => DBUS_TYPE_INT32
366 float => DBUS_TYPE_DOUBLE
367 string => DBUS_TYPE_STRING
368 list => DBUS_TYPE_ARRAY
369
370All arguments can be preceded by a type symbol. For details about
371type symbols, see Info node `(dbus)Type Conversion'.
372
373Example:
374
375\(dbus-send-signal
376 :session nil \"/org/gnu/Emacs\" \"org.gnu.Emacs.FileManager\"
377 \"FileModified\" \"/home/albinus/.emacs\")"
378
379 (or (memq bus '(:system :session)) (stringp bus)
380 (signal 'wrong-type-argument (list 'keywordp bus)))
381 (or (null service) (stringp service)
382 (signal 'wrong-type-argument (list 'stringp service)))
383 (or (stringp path)
384 (signal 'wrong-type-argument (list 'stringp path)))
385 (or (stringp interface)
386 (signal 'wrong-type-argument (list 'stringp interface)))
387 (or (stringp signal)
388 (signal 'wrong-type-argument (list 'stringp signal)))
389
390 (apply 'dbus-message-internal dbus-message-type-signal
391 bus service path interface signal args))
392
393(defun dbus-method-return-internal (bus service serial &rest args)
394 "Return for message SERIAL on the D-Bus BUS.
395This is an internal function, it shall not be used outside dbus.el."
396
397 (or (memq bus '(:system :session)) (stringp bus)
398 (signal 'wrong-type-argument (list 'keywordp bus)))
399 (or (stringp service)
400 (signal 'wrong-type-argument (list 'stringp service)))
401 (or (natnump serial)
402 (signal 'wrong-type-argument (list 'natnump serial)))
403
404 (apply 'dbus-message-internal dbus-message-type-method-return
405 bus service serial args))
406
407(defun dbus-method-error-internal (bus service serial &rest args)
408 "Return error message for message SERIAL on the D-Bus BUS.
409This is an internal function, it shall not be used outside dbus.el."
410
411 (or (memq bus '(:system :session)) (stringp bus)
412 (signal 'wrong-type-argument (list 'keywordp bus)))
413 (or (stringp service)
414 (signal 'wrong-type-argument (list 'stringp service)))
415 (or (natnump serial)
416 (signal 'wrong-type-argument (list 'natnump serial)))
417
418 (apply 'dbus-message-internal dbus-message-type-error
419 bus service serial args))
420
421
422;;; Hash table of registered functions.
117 423
118(defun dbus-list-hash-table () 424(defun dbus-list-hash-table ()
119 "Returns all registered member registrations to D-Bus. 425 "Returns all registered member registrations to D-Bus.
@@ -126,69 +432,78 @@ hash table."
126 dbus-registered-objects-table) 432 dbus-registered-objects-table)
127 result)) 433 result))
128 434
129(defun dbus-unregister-object (object) 435(defun dbus-setenv (bus variable value)
130 "Unregister OBJECT from D-Bus. 436 "Set the value of the BUS environment variable named VARIABLE to VALUE.
131OBJECT must be the result of a preceding `dbus-register-method',
132`dbus-register-property' or `dbus-register-signal' call. It
133returns `t' if OBJECT has been unregistered, `nil' otherwise.
134 437
135When OBJECT identifies the last method or property, which is 438BUS is either a Lisp symbol, `:system' or `:session', or a string
136registered for the respective service, Emacs releases its 439denoting the bus address. Both VARIABLE and VALUE should be strings.
137association to the service from D-Bus."
138 ;; Check parameter.
139 (unless (and (consp object) (not (null (car object))) (consp (cdr object)))
140 (signal 'wrong-type-argument (list 'D-Bus object)))
141 440
142 ;; Find the corresponding entry in the hash table. 441Normally, services inherit the environment of the BUS daemon. This
143 (let* ((key (car object)) 442function adds to or modifies that environment when activating services.
144 (value (cadr object))
145 (bus (car key))
146 (service (car value))
147 (entry (gethash key dbus-registered-objects-table))
148 ret)
149 ;; key has the structure (BUS INTERFACE MEMBER).
150 ;; value has the structure (SERVICE PATH [HANDLER]).
151 ;; entry has the structure ((UNAME SERVICE PATH MEMBER [RULE]) ...).
152 ;; MEMBER is either a string (the handler), or a cons cell (a
153 ;; property value). UNAME and property values are not taken into
154 ;; account for comparison.
155 443
156 ;; Loop over the registered functions. 444Some bus instances, such as `:system', may disable setting the environment."
157 (dolist (elt entry) 445 (dbus-call-method
158 (when (equal 446 bus dbus-service-dbus dbus-path-dbus
159 value 447 dbus-interface-dbus "UpdateActivationEnvironment"
160 (butlast (cdr elt) (- (length (cdr elt)) (length value)))) 448 `(:array (:dict-entry ,variable ,value))))
161 (setq ret t) 449
162 ;; Compute new hash value. If it is empty, remove it from the 450(defun dbus-register-service (bus service &rest flags)
163 ;; hash table. 451 "Register known name SERVICE on the D-Bus BUS.
164 (unless (puthash key (delete elt entry) dbus-registered-objects-table) 452
165 (remhash key dbus-registered-objects-table)) 453BUS is either a Lisp symbol, `:system' or `:session', or a string
166 ;; Remove match rule of signals. 454denoting the bus address.
167 (let ((rule (nth 4 elt))) 455
168 (when (stringp rule) 456SERVICE is the D-Bus service name that should be registered. It must
169 (setq service nil) ; We do not need to unregister the service. 457be a known name.
170 (dbus-call-method 458
171 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus 459FLAGS are keywords, which control how the service name is registered.
172 "RemoveMatch" rule))))) 460The following keywords are recognized:
173 ;; Check, whether there is still a registered function or property 461
174 ;; for the given service. If not, unregister the service from the 462`:allow-replacement': Allow another service to become the primary
175 ;; bus. 463owner if requested.
176 (when service 464
177 (dolist (elt entry) 465`:replace-existing': Request to replace the current primary owner.
178 (let (found) 466
179 (maphash 467`:do-not-queue': If we can not become the primary owner do not place
180 (lambda (k v) 468us in the queue.
181 (dolist (e v) 469
182 (ignore-errors 470The function returns a keyword, indicating the result of the
183 (when (and (equal bus (car k)) (string-equal service (cadr e))) 471operation. One of the following keywords is returned:
184 (setq found t))))) 472
185 dbus-registered-objects-table) 473`:primary-owner': Service has become the primary owner of the
186 (unless found 474requested name.
187 (dbus-call-method 475
188 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus 476`:in-queue': Service could not become the primary owner and has been
189 "ReleaseName" service))))) 477placed in the queue.
190 ;; Return. 478
191 ret)) 479`:exists': Service is already in the queue.
480
481`:already-owner': Service is already the primary owner."
482
483 ;; Add ObjectManager handler.
484 (dbus-register-method
485 bus service nil dbus-interface-objectmanager "GetManagedObjects"
486 'dbus-managed-objects-handler 'dont-register)
487
488 (let ((arg 0)
489 reply)
490 (dolist (flag flags)
491 (setq arg
492 (+ arg
493 (case flag
494 (:allow-replacement 1)
495 (:replace-existing 2)
496 (:do-not-queue 4)
497 (t (signal 'wrong-type-argument (list flag)))))))
498 (setq reply (dbus-call-method
499 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
500 "RequestName" service arg))
501 (case reply
502 (1 :primary-owner)
503 (2 :in-queue)
504 (3 :exists)
505 (4 :already-owner)
506 (t (signal 'dbus-error (list "Could not register service" service))))))
192 507
193(defun dbus-unregister-service (bus service) 508(defun dbus-unregister-service (bus service)
194 "Unregister all objects related to SERVICE from D-Bus BUS. 509 "Unregister all objects related to SERVICE from D-Bus BUS.
@@ -209,7 +524,7 @@ queue of this service."
209 (lambda (key value) 524 (lambda (key value)
210 (dolist (elt value) 525 (dolist (elt value)
211 (ignore-errors 526 (ignore-errors
212 (when (and (equal bus (car key)) (string-equal service (cadr elt))) 527 (when (and (equal bus (cadr key)) (string-equal service (cadr elt)))
213 (unless 528 (unless
214 (puthash key (delete elt value) dbus-registered-objects-table) 529 (puthash key (delete elt value) dbus-registered-objects-table)
215 (remhash key dbus-registered-objects-table)))))) 530 (remhash key dbus-registered-objects-table))))))
@@ -223,94 +538,274 @@ queue of this service."
223 (3 :not-owner) 538 (3 :not-owner)
224 (t (signal 'dbus-error (list "Could not unregister service" service)))))) 539 (t (signal 'dbus-error (list "Could not unregister service" service))))))
225 540
226(defun dbus-call-method-non-blocking-handler (&rest args) 541(defun dbus-register-signal
227 "Handler for reply messages of asynchronous D-Bus message calls. 542 (bus service path interface signal handler &rest args)
228It calls the function stored in `dbus-registered-objects-table'. 543 "Register for a signal on the D-Bus BUS.
229The result will be made available in `dbus-return-values-table'."
230 (puthash (list (dbus-event-bus-name last-input-event)
231 (dbus-event-serial-number last-input-event))
232 (if (= (length args) 1) (car args) args)
233 dbus-return-values-table))
234 544
235(defun dbus-call-method-non-blocking 545BUS is either a Lisp symbol, `:system' or `:session', or a string
236 (bus service path interface method &rest args) 546denoting the bus address.
237 "Call METHOD on the D-Bus BUS, but don't block the event queue.
238This is necessary for communicating to registered D-Bus methods,
239which are running in the same Emacs process.
240 547
241The arguments are the same as in `dbus-call-method'. 548SERVICE is the D-Bus service name used by the sending D-Bus object.
549It can be either a known name or the unique name of the D-Bus object
550sending the signal.
551
552PATH is the D-Bus object path SERVICE is registered. INTERFACE
553is an interface offered by SERVICE. It must provide SIGNAL.
554HANDLER is a Lisp function to be called when the signal is
555received. It must accept as arguments the values SIGNAL is
556sending.
557
558SERVICE, PATH, INTERFACE and SIGNAL can be nil. This is
559interpreted as a wildcard for the respective argument.
560
561The remaining arguments ARGS can be keywords or keyword string pairs.
562The meaning is as follows:
563
564`:argN' STRING:
565`:pathN' STRING: This stands for the Nth argument of the
566signal. `:pathN' arguments can be used for object path wildcard
567matches as specified by D-Bus, whilest an `:argN' argument
568requires an exact match.
569
570`:arg-namespace' STRING: Register for the signals, which first
571argument defines the service or interface namespace STRING.
572
573`:path-namespace' STRING: Register for the object path namespace
574STRING. All signals sent from an object path, which has STRING as
575the preceding string, are matched. This requires PATH to be nil.
576
577`:eavesdrop': Register for unicast signals which are not directed
578to the D-Bus object Emacs is registered at D-Bus BUS, if the
579security policy of BUS allows this.
580
581Example:
582
583\(defun my-signal-handler (device)
584 (message \"Device %s added\" device))
585
586\(dbus-register-signal
587 :system \"org.freedesktop.Hal\" \"/org/freedesktop/Hal/Manager\"
588 \"org.freedesktop.Hal.Manager\" \"DeviceAdded\" 'my-signal-handler)
589
590 => \(\(:signal :system \"org.freedesktop.Hal.Manager\" \"DeviceAdded\")
591 \(\"org.freedesktop.Hal\" \"/org/freedesktop/Hal/Manager\" my-signal-handler))
592
593`dbus-register-signal' returns an object, which can be used in
594`dbus-unregister-object' for removing the registration."
595
596 (let ((counter 0)
597 (rule "type='signal'")
598 uname key key1 value)
599
600 ;; Retrieve unique name of service. If service is a known name,
601 ;; we will register for the corresponding unique name, if any.
602 ;; Signals are sent always with the unique name as sender. Note:
603 ;; the unique name of `dbus-service-dbus' is that string itself.
604 (if (and (stringp service)
605 (not (zerop (length service)))
606 (not (string-equal service dbus-service-dbus))
607 (not (string-match "^:" service)))
608 (setq uname (dbus-get-name-owner bus service))
609 (setq uname service))
610
611 (setq rule (concat rule
612 (when uname (format ",sender='%s'" uname))
613 (when interface (format ",interface='%s'" interface))
614 (when signal (format ",member='%s'" signal))
615 (when path (format ",path='%s'" path))))
616
617 ;; Add arguments to the rule.
618 (if (or (stringp (car args)) (null (car args)))
619 ;; As backward compatibility option, we allow just strings.
620 (dolist (arg args)
621 (if (stringp arg)
622 (setq rule (concat rule (format ",arg%d='%s'" counter arg)))
623 (if arg (signal 'wrong-type-argument (list "Wrong argument" arg))))
624 (setq counter (1+ counter)))
625
626 ;; Parse keywords.
627 (while args
628 (setq
629 key (car args)
630 rule (concat
631 rule
632 (cond
633 ;; `:arg0' .. `:arg63', `:path0' .. `:path63'.
634 ((and (keywordp key)
635 (string-match
636 "^:\\(arg\\|path\\)\\([[:digit:]]+\\)$"
637 (symbol-name key)))
638 (setq counter (match-string 2 (symbol-name key))
639 args (cdr args)
640 value (car args))
641 (unless (and (<= counter 63) (stringp value))
642 (signal 'wrong-type-argument
643 (list "Wrong argument" key value)))
644 (format
645 ",arg%s%s='%s'"
646 counter
647 (if (string-equal (match-string 1 (symbol-name key)) "path")
648 "path" "")
649 value))
650 ;; `:arg-namespace', `:path-namespace'.
651 ((and (keywordp key)
652 (string-match
653 "^:\\(arg\\|path\\)-namespace$" (symbol-name key)))
654 (setq args (cdr args)
655 value (car args))
656 (unless (stringp value)
657 (signal 'wrong-type-argument
658 (list "Wrong argument" key value)))
659 (format
660 ",%s='%s'"
661 (if (string-equal (match-string 1 (symbol-name key)) "path")
662 "path_namespace" "arg0namespace")
663 value))
664 ;; `:eavesdrop'.
665 ((eq key :eavesdrop)
666 ",eavesdrop='true'")
667 (t (signal 'wrong-type-argument (list "Wrong argument" key)))))
668 args (cdr args))))
669
670 ;; Add the rule to the bus.
671 (condition-case err
672 (dbus-call-method
673 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
674 "AddMatch" rule)
675 (dbus-error
676 (if (not (string-match "eavesdrop" rule))
677 (signal (car err) (cdr err))
678 ;; The D-Bus spec says we shall fall back to a rule without eavesdrop.
679 (when dbus-debug (message "Removing eavesdrop from rule %s" rule))
680 (setq rule (replace-regexp-in-string ",eavesdrop='true'" "" rule))
681 (dbus-call-method
682 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
683 "AddMatch" rule))))
242 684
243usage: (dbus-call-method-non-blocking 685 (when dbus-debug (message "Matching rule \"%s\" created" rule))
244 BUS SERVICE PATH INTERFACE METHOD
245 &optional :timeout TIMEOUT &rest ARGS)"
246 686
247 (let ((key 687 ;; Create a hash table entry.
248 (apply 688 (setq key (list :signal bus interface signal)
249 'dbus-call-method-asynchronously 689 key1 (list uname service path handler rule)
250 bus service path interface method 690 value (gethash key dbus-registered-objects-table))
251 'dbus-call-method-non-blocking-handler args))) 691 (unless (member key1 value)
252 ;; Wait until `dbus-call-method-non-blocking-handler' has put the 692 (puthash key (cons key1 value) dbus-registered-objects-table))
253 ;; result into `dbus-return-values-table'.
254 (while (eq (gethash key dbus-return-values-table :ignore) :ignore)
255 (read-event nil nil 0.1))
256 693
257 ;; Cleanup `dbus-return-values-table'. Return the result. 694 ;; Return the object.
258 (prog1 695 (list key (list service path handler))))
259 (gethash key dbus-return-values-table nil)
260 (remhash key dbus-return-values-table))))
261 696
262(defun dbus-name-owner-changed-handler (&rest args) 697(defun dbus-register-method
263 "Reapplies all member registrations to D-Bus. 698 (bus service path interface method handler &optional dont-register-service)
264This handler is applied when a \"NameOwnerChanged\" signal has 699 "Register for method METHOD on the D-Bus BUS.
265arrived. SERVICE is the object name for which the name owner has 700
266been changed. OLD-OWNER is the previous owner of SERVICE, or the 701BUS is either a Lisp symbol, `:system' or `:session', or a string
267empty string if SERVICE was not owned yet. NEW-OWNER is the new 702denoting the bus address.
268owner of SERVICE, or the empty string if SERVICE loses any name owner. 703
269 704SERVICE is the D-Bus service name of the D-Bus object METHOD is
270usage: (dbus-name-owner-changed-handler service old-owner new-owner)" 705registered for. It must be a known name (See discussion of
271 (save-match-data 706DONT-REGISTER-SERVICE below).
272 ;; Check the arguments. We should silently ignore it when they 707
273 ;; are wrong. 708PATH is the D-Bus object path SERVICE is registered (See discussion of
274 (if (and (= (length args) 3) 709DONT-REGISTER-SERVICE below). INTERFACE is the interface offered by
275 (stringp (car args)) 710SERVICE. It must provide METHOD.
276 (stringp (cadr args)) 711
277 (stringp (caddr args))) 712HANDLER is a Lisp function to be called when a method call is
278 (let ((service (car args)) 713received. It must accept the input arguments of METHOD. The return
279 (old-owner (cadr args))) 714value of HANDLER is used for composing the returning D-Bus message.
280 ;; Check whether SERVICE is a known name. 715In case HANDLER shall return a reply message with an empty argument
281 (when (not (string-match "^:" service)) 716list, HANDLER must return the symbol `:ignore'.
282 (maphash 717
283 (lambda (key value) 718When DONT-REGISTER-SERVICE is non-nil, the known name SERVICE is not
284 (dolist (elt value) 719registered. This means that other D-Bus clients have no way of
285 ;; key has the structure (BUS INTERFACE MEMBER). 720noticing the newly registered method. When interfaces are constructed
286 ;; elt has the structure (UNAME SERVICE PATH HANDLER). 721incrementally by adding single methods or properties at a time,
287 (when (string-equal old-owner (car elt)) 722DONT-REGISTER-SERVICE can be used to prevent other clients from
288 ;; Remove old key, and add new entry with changed name. 723discovering the still incomplete interface."
289 (dbus-unregister-object (list key (cdr elt))) 724
290 ;; Maybe we could arrange the lists a little bit better 725 ;; Register SERVICE.
291 ;; that we don't need to extract every single element? 726 (unless (or dont-register-service
292 (dbus-register-signal 727 (member service (dbus-list-names bus)))
293 ;; BUS SERVICE PATH 728 (dbus-register-service bus service))
294 (nth 0 key) (nth 1 elt) (nth 2 elt) 729
295 ;; INTERFACE MEMBER HANDLER 730 ;; Create a hash table entry. We use nil for the unique name,
296 (nth 1 key) (nth 2 key) (nth 3 elt))))) 731 ;; because the method might be called from anybody.
297 (copy-hash-table dbus-registered-objects-table)))) 732 (let* ((key (list :method bus interface method))
298 ;; The error is reported only in debug mode. 733 (key1 (list nil service path handler))
299 (when dbus-debug 734 (value (gethash key dbus-registered-objects-table)))
300 (signal 735
301 'dbus-error 736 (unless (member key1 value)
302 (cons 737 (puthash key (cons key1 value) dbus-registered-objects-table))
303 (format "Wrong arguments of %s.NameOwnerChanged" dbus-interface-dbus) 738
304 args)))))) 739 ;; Return the object.
305 740 (list key (list service path handler))))
306;; Register the handler. 741
307(when nil ;ignore-errors 742(defun dbus-unregister-object (object)
308 (dbus-register-signal 743 "Unregister OBJECT from D-Bus.
309 :system dbus-service-dbus dbus-path-dbus dbus-interface-dbus 744OBJECT must be the result of a preceding `dbus-register-method',
310 "NameOwnerChanged" 'dbus-name-owner-changed-handler) 745`dbus-register-property' or `dbus-register-signal' call. It
311 (dbus-register-signal 746returns `t' if OBJECT has been unregistered, `nil' otherwise.
312 :session dbus-service-dbus dbus-path-dbus dbus-interface-dbus 747
313 "NameOwnerChanged" 'dbus-name-owner-changed-handler)) 748When OBJECT identifies the last method or property, which is
749registered for the respective service, Emacs releases its
750association to the service from D-Bus."
751 ;; Check parameter.
752 (unless (and (consp object) (not (null (car object))) (consp (cdr object)))
753 (signal 'wrong-type-argument (list 'D-Bus object)))
754
755 ;; Find the corresponding entry in the hash table.
756 (let* ((key (car object))
757 (type (car key))
758 (bus (cadr key))
759 (value (cadr object))
760 (service (car value))
761 (entry (gethash key dbus-registered-objects-table))
762 ret)
763 ;; key has the structure (TYPE BUS INTERFACE MEMBER).
764 ;; value has the structure (SERVICE PATH [HANDLER]).
765 ;; entry has the structure ((UNAME SERVICE PATH MEMBER [RULE]) ...).
766 ;; MEMBER is either a string (the handler), or a cons cell (a
767 ;; property value). UNAME and property values are not taken into
768 ;; account for comparison.
769
770 ;; Loop over the registered functions.
771 (dolist (elt entry)
772 (when (equal
773 value
774 (butlast (cdr elt) (- (length (cdr elt)) (length value))))
775 (setq ret t)
776 ;; Compute new hash value. If it is empty, remove it from the
777 ;; hash table.
778 (unless (puthash key (delete elt entry) dbus-registered-objects-table)
779 (remhash key dbus-registered-objects-table))
780 ;; Remove match rule of signals.
781 (when (eq type :signal)
782 (dbus-call-method
783 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
784 "RemoveMatch" (nth 4 elt)))))
785
786 ;; Check, whether there is still a registered function or property
787 ;; for the given service. If not, unregister the service from the
788 ;; bus.
789 (when (and service (memq type '(:method :property))
790 (not (catch :found
791 (progn
792 (maphash
793 (lambda (k v)
794 (dolist (e v)
795 (ignore-errors
796 (and
797 ;; Bus.
798 (equal bus (cadr k))
799 ;; Service.
800 (string-equal service (cadr e))
801 ;; Non-empty object path.
802 (caddr e)
803 (throw :found t)))))
804 dbus-registered-objects-table)
805 nil))))
806 (dbus-unregister-service bus service))
807 ;; Return.
808 ret))
314 809
315 810
316;;; D-Bus type conversion. 811;;; D-Bus type conversion.
@@ -437,9 +932,9 @@ If the HANDLER returns a `dbus-error', it is propagated as return message."
437 (dbus-ignore-errors 932 (dbus-ignore-errors
438 (if (eq result :ignore) 933 (if (eq result :ignore)
439 (dbus-method-return-internal 934 (dbus-method-return-internal
440 (nth 1 event) (nth 3 event) (nth 4 event)) 935 (nth 1 event) (nth 4 event) (nth 3 event))
441 (apply 'dbus-method-return-internal 936 (apply 'dbus-method-return-internal
442 (nth 1 event) (nth 3 event) (nth 4 event) 937 (nth 1 event) (nth 4 event) (nth 3 event)
443 (if (consp result) result (list result))))))) 938 (if (consp result) result (list result)))))))
444 ;; Error handling. 939 ;; Error handling.
445 (dbus-error 940 (dbus-error
@@ -447,7 +942,7 @@ If the HANDLER returns a `dbus-error', it is propagated as return message."
447 (when (= dbus-message-type-method-call (nth 2 event)) 942 (when (= dbus-message-type-method-call (nth 2 event))
448 (dbus-ignore-errors 943 (dbus-ignore-errors
449 (dbus-method-error-internal 944 (dbus-method-error-internal
450 (nth 1 event) (nth 3 event) (nth 4 event) (cadr err)))) 945 (nth 1 event) (nth 4 event) (nth 3 event) (cadr err))))
451 ;; Propagate D-Bus error messages. 946 ;; Propagate D-Bus error messages.
452 (run-hook-with-args 'dbus-event-error-hooks event err) 947 (run-hook-with-args 'dbus-event-error-hooks event err)
453 (when (or dbus-debug (= dbus-message-type-error (nth 2 event))) 948 (when (or dbus-debug (= dbus-message-type-error (nth 2 event)))
@@ -596,11 +1091,11 @@ are strings. The result, the introspection data, is a string in
596XML format." 1091XML format."
597 ;; We don't want to raise errors. `dbus-call-method-non-blocking' 1092 ;; We don't want to raise errors. `dbus-call-method-non-blocking'
598 ;; is used, because the handler can be registered in our Emacs 1093 ;; is used, because the handler can be registered in our Emacs
599 ;; instance; caller an callee would block each other. 1094 ;; instance; caller and callee would block each other.
600 (dbus-ignore-errors 1095 (dbus-ignore-errors
601 (funcall 1096 (dbus-call-method
602 (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking) 1097 bus service path dbus-interface-introspectable "Introspect"
603 bus service path dbus-interface-introspectable "Introspect"))) 1098 :timeout 1000)))
604 1099
605(defun dbus-introspect-xml (bus service path) 1100(defun dbus-introspect-xml (bus service path)
606 "Return the introspection data of SERVICE in D-Bus BUS at object path PATH. 1101 "Return the introspection data of SERVICE in D-Bus BUS at object path PATH.
@@ -854,12 +1349,11 @@ be \"out\"."
854It will be checked at BUS, SERVICE, PATH. The result can be any 1349It will be checked at BUS, SERVICE, PATH. The result can be any
855valid D-Bus value, or `nil' if there is no PROPERTY." 1350valid D-Bus value, or `nil' if there is no PROPERTY."
856 (dbus-ignore-errors 1351 (dbus-ignore-errors
857 ;; "Get" returns a variant, so we must use the `car'. 1352 ;; "Get" returns a variant, so we must use the `car'.
858 (car 1353 (car
859 (funcall 1354 (dbus-call-method
860 (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking) 1355 bus service path dbus-interface-properties
861 bus service path dbus-interface-properties 1356 "Get" :timeout 500 interface property))))
862 "Get" :timeout 500 interface property))))
863 1357
864(defun dbus-set-property (bus service path interface property value) 1358(defun dbus-set-property (bus service path interface property value)
865 "Set value of PROPERTY of INTERFACE to VALUE. 1359 "Set value of PROPERTY of INTERFACE to VALUE.
@@ -867,13 +1361,12 @@ It will be checked at BUS, SERVICE, PATH. When the value has
867been set successful, the result is VALUE. Otherwise, `nil' is 1361been set successful, the result is VALUE. Otherwise, `nil' is
868returned." 1362returned."
869 (dbus-ignore-errors 1363 (dbus-ignore-errors
870 ;; "Set" requires a variant. 1364 ;; "Set" requires a variant.
871 (funcall 1365 (dbus-call-method
872 (if noninteractive 'dbus-call-method 'dbus-call-method-non-blocking) 1366 bus service path dbus-interface-properties
873 bus service path dbus-interface-properties 1367 "Set" :timeout 500 interface property (list :variant value))
874 "Set" :timeout 500 interface property (list :variant value)) 1368 ;; Return VALUE.
875 ;; Return VALUE. 1369 (dbus-get-property bus service path interface property)))
876 (dbus-get-property bus service path interface property)))
877 1370
878(defun dbus-get-all-properties (bus service path interface) 1371(defun dbus-get-all-properties (bus service path interface)
879 "Return all properties of INTERFACE at BUS, SERVICE, PATH. 1372 "Return all properties of INTERFACE at BUS, SERVICE, PATH.
@@ -884,10 +1377,7 @@ name of the property, and its value. If there are no properties,
884 ;; "GetAll" returns "a{sv}". 1377 ;; "GetAll" returns "a{sv}".
885 (let (result) 1378 (let (result)
886 (dolist (dict 1379 (dolist (dict
887 (funcall 1380 (dbus-call-method
888 (if noninteractive
889 'dbus-call-method
890 'dbus-call-method-non-blocking)
891 bus service path dbus-interface-properties 1381 bus service path dbus-interface-properties
892 "GetAll" :timeout 500 interface) 1382 "GetAll" :timeout 500 interface)
893 result) 1383 result)
@@ -931,14 +1421,7 @@ constructed incrementally by adding single methods or properties
931at a time, DONT-REGISTER-SERVICE can be used to prevent other 1421at a time, DONT-REGISTER-SERVICE can be used to prevent other
932clients from discovering the still incomplete interface." 1422clients from discovering the still incomplete interface."
933 (unless (member access '(:read :readwrite)) 1423 (unless (member access '(:read :readwrite))
934 (signal 'dbus-error (list "Access type invalid" access))) 1424 (signal 'wrong-type-argument (list "Access type invalid" access)))
935
936 ;; Register SERVICE.
937 (unless (or dont-register-service
938 (member service (dbus-list-names bus)))
939 (dbus-call-method
940 bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
941 "RequestName" service 0))
942 1425
943 ;; Add handlers for the three property-related methods. 1426 ;; Add handlers for the three property-related methods.
944 (dbus-register-method 1427 (dbus-register-method
@@ -951,20 +1434,20 @@ clients from discovering the still incomplete interface."
951 bus service path dbus-interface-properties "Set" 1434 bus service path dbus-interface-properties "Set"
952 'dbus-property-handler 'dont-register) 1435 'dbus-property-handler 'dont-register)
953 1436
954 ;; Register the name SERVICE with BUS. 1437 ;; Register SERVICE.
955 (unless dont-register-service 1438 (unless (or dont-register-service (member service (dbus-list-names bus)))
956 (dbus-register-service bus service)) 1439 (dbus-register-service bus service))
957 1440
958 ;; Send the PropertiesChanged signal. 1441 ;; Send the PropertiesChanged signal.
959 (when emits-signal 1442 (when emits-signal
960 (dbus-send-signal 1443 (dbus-send-signal
961 bus service path dbus-interface-properties "PropertiesChanged" 1444 bus service path dbus-interface-properties "PropertiesChanged"
962 (list (list :dict-entry property (list :variant value))) 1445 `((:dict-entry ,property (:variant ,value)))
963 '(:array))) 1446 '(:array)))
964 1447
965 ;; Create a hash table entry. We use nil for the unique name, 1448 ;; Create a hash table entry. We use nil for the unique name,
966 ;; because the property might be accessed from anybody. 1449 ;; because the property might be accessed from anybody.
967 (let ((key (list bus interface property)) 1450 (let ((key (list :property bus interface property))
968 (val 1451 (val
969 (list 1452 (list
970 (list 1453 (list
@@ -979,7 +1462,7 @@ clients from discovering the still incomplete interface."
979 1462
980(defun dbus-property-handler (&rest args) 1463(defun dbus-property-handler (&rest args)
981 "Default handler for the \"org.freedesktop.DBus.Properties\" interface. 1464 "Default handler for the \"org.freedesktop.DBus.Properties\" interface.
982It will be registered for all objects created by `dbus-register-object'." 1465It will be registered for all objects created by `dbus-register-property'."
983 (let ((bus (dbus-event-bus-name last-input-event)) 1466 (let ((bus (dbus-event-bus-name last-input-event))
984 (service (dbus-event-service-name last-input-event)) 1467 (service (dbus-event-service-name last-input-event))
985 (path (dbus-event-path-name last-input-event)) 1468 (path (dbus-event-path-name last-input-event))
@@ -989,15 +1472,15 @@ It will be registered for all objects created by `dbus-register-object'."
989 (cond 1472 (cond
990 ;; "Get" returns a variant. 1473 ;; "Get" returns a variant.
991 ((string-equal method "Get") 1474 ((string-equal method "Get")
992 (let ((entry (gethash (list bus interface property) 1475 (let ((entry (gethash (list :property bus interface property)
993 dbus-registered-objects-table))) 1476 dbus-registered-objects-table)))
994 (when (string-equal path (nth 2 (car entry))) 1477 (when (string-equal path (nth 2 (car entry)))
995 (list (list :variant (cdar (last (car entry)))))))) 1478 `((:variant ,(cdar (last (car entry))))))))
996 1479
997 ;; "Set" expects a variant. 1480 ;; "Set" expects a variant.
998 ((string-equal method "Set") 1481 ((string-equal method "Set")
999 (let* ((value (caar (cddr args))) 1482 (let* ((value (caar (cddr args)))
1000 (entry (gethash (list bus interface property) 1483 (entry (gethash (list :property bus interface property)
1001 dbus-registered-objects-table)) 1484 dbus-registered-objects-table))
1002 ;; The value of the hash table is a list; in case of 1485 ;; The value of the hash table is a list; in case of
1003 ;; properties it contains just one element (UNAME SERVICE 1486 ;; properties it contains just one element (UNAME SERVICE
@@ -1012,7 +1495,7 @@ It will be registered for all objects created by `dbus-register-object'."
1012 (unless (member :readwrite (car object)) 1495 (unless (member :readwrite (car object))
1013 (signal 'dbus-error 1496 (signal 'dbus-error
1014 (list "Property not writable at path" property path))) 1497 (list "Property not writable at path" property path)))
1015 (puthash (list bus interface property) 1498 (puthash (list :property bus interface property)
1016 (list (append (butlast (car entry)) 1499 (list (append (butlast (car entry))
1017 (list (cons (car object) value)))) 1500 (list (cons (car object) value))))
1018 dbus-registered-objects-table) 1501 dbus-registered-objects-table)
@@ -1020,7 +1503,7 @@ It will be registered for all objects created by `dbus-register-object'."
1020 (when (member :emits-signal (car object)) 1503 (when (member :emits-signal (car object))
1021 (dbus-send-signal 1504 (dbus-send-signal
1022 bus service path dbus-interface-properties "PropertiesChanged" 1505 bus service path dbus-interface-properties "PropertiesChanged"
1023 (list (list :dict-entry property (list :variant value))) 1506 `((:dict-entry ,property (:variant ,value)))
1024 '(:array))) 1507 '(:array)))
1025 ;; Return empty reply. 1508 ;; Return empty reply.
1026 :ignore)) 1509 :ignore))
@@ -1030,7 +1513,7 @@ It will be registered for all objects created by `dbus-register-object'."
1030 (let (result) 1513 (let (result)
1031 (maphash 1514 (maphash
1032 (lambda (key val) 1515 (lambda (key val)
1033 (when (and (equal (butlast key) (list bus interface)) 1516 (when (and (equal (butlast key) (list :property bus interface))
1034 (string-equal path (nth 2 (car val))) 1517 (string-equal path (nth 2 (car val)))
1035 (not (functionp (car (last (car val)))))) 1518 (not (functionp (car (last (car val))))))
1036 (add-to-list 1519 (add-to-list
@@ -1042,15 +1525,151 @@ It will be registered for all objects created by `dbus-register-object'."
1042 ;; Return the result, or an empty array. 1525 ;; Return the result, or an empty array.
1043 (list :array (or result '(:signature "{sv}")))))))) 1526 (list :array (or result '(:signature "{sv}"))))))))
1044 1527
1528
1529;;; D-Bus object manager.
1530
1531(defun dbus-get-all-managed-objects (bus service path)
1532 "Return all objects at BUS, SERVICE, PATH, and the children of PATH.
1533The result is a list of objects. Every object is a cons of an
1534existing path name, and the list of available interface objects.
1535An interface object is another cons, which car is the interface
1536name, and the cdr is the list of properties as returned by
1537`dbus-get-all-properties' for that path and interface. Example:
1538
1539\(dbus-get-all-managed-objects :session \"org.gnome.SettingsDaemon\" \"/\")
1540
1541 => \(\(\"/org/gnome/SettingsDaemon/MediaKeys\"
1542 \(\"org.gnome.SettingsDaemon.MediaKeys\")
1543 \(\"org.freedesktop.DBus.Peer\")
1544 \(\"org.freedesktop.DBus.Introspectable\")
1545 \(\"org.freedesktop.DBus.Properties\")
1546 \(\"org.freedesktop.DBus.ObjectManager\"))
1547 \(\"/org/gnome/SettingsDaemon/Power\"
1548 \(\"org.gnome.SettingsDaemon.Power.Keyboard\")
1549 \(\"org.gnome.SettingsDaemon.Power.Screen\")
1550 \(\"org.gnome.SettingsDaemon.Power\"
1551 \(\"Icon\" . \". GThemedIcon battery-full-charged-symbolic \")
1552 \(\"Tooltip\" . \"Laptop battery is charged\"))
1553 \(\"org.freedesktop.DBus.Peer\")
1554 \(\"org.freedesktop.DBus.Introspectable\")
1555 \(\"org.freedesktop.DBus.Properties\")
1556 \(\"org.freedesktop.DBus.ObjectManager\"))
1557 ...)
1558
1559If possible, \"org.freedesktop.DBus.ObjectManager.GetManagedObjects\"
1560is used for retrieving the information. Otherwise, the information
1561is collected via \"org.freedesktop.DBus.Introspectable.Introspect\"
1562and \"org.freedesktop.DBus.Properties.GetAll\", which is slow."
1563 (let ((result
1564 ;; Direct call. Fails, if the target does not support the
1565 ;; object manager interface.
1566 (dbus-ignore-errors
1567 (dbus-call-method
1568 bus service path dbus-interface-objectmanager
1569 "GetManagedObjects" :timeout 1000))))
1570
1571 (if result
1572 ;; Massage the returned structure.
1573 (dolist (entry result result)
1574 ;; "a{oa{sa{sv}}}".
1575 (dolist (entry1 (cdr entry))
1576 ;; "a{sa{sv}}".
1577 (dolist (entry2 entry1)
1578 ;; "a{sv}".
1579 (if (cadr entry2)
1580 ;; "sv".
1581 (dolist (entry3 (cadr entry2))
1582 (setcdr entry3 (caadr entry3)))
1583 (setcdr entry2 nil)))))
1584
1585 ;; Fallback: collect the information. Slooow!
1586 (dolist (object
1587 (dbus-introspect-get-all-nodes bus service path)
1588 result)
1589 (let (result1)
1590 (dolist
1591 (interface
1592 (dbus-introspect-get-interface-names bus service object)
1593 result1)
1594 (add-to-list
1595 'result1
1596 (cons interface
1597 (dbus-get-all-properties bus service object interface))))
1598 (when result1
1599 (add-to-list 'result (cons object result1))))))))
1600
1601(defun dbus-managed-objects-handler ()
1602 "Default handler for the \"org.freedesktop.DBus.ObjectManager\" interface.
1603It will be registered for all objects created by `dbus-register-method'."
1604 (let* ((last-input-event last-input-event)
1605 (bus (dbus-event-bus-name last-input-event))
1606 (service (dbus-event-service-name last-input-event))
1607 (path (dbus-event-path-name last-input-event)))
1608 ;; "GetManagedObjects" returns "a{oa{sa{sv}}}".
1609 (let (interfaces result)
1610
1611 ;; Check for object path wildcard interfaces.
1612 (maphash
1613 (lambda (key val)
1614 (when (and (equal (butlast key 2) (list :method bus))
1615 (null (nth 2 (car-safe val))))
1616 (add-to-list 'interfaces (nth 2 key))))
1617 dbus-registered-objects-table)
1618
1619 ;; Check all registered object paths.
1620 (maphash
1621 (lambda (key val)
1622 (let ((object (or (nth 2 (car-safe val)) ""))
1623 (interface (nth 2 key)))
1624 (when (and (equal (butlast key 2) (list :method bus))
1625 (string-prefix-p path object))
1626 (dolist (interface (cons (nth 2 key) interfaces))
1627 (unless (assoc object result)
1628 (add-to-list 'result (list object)))
1629 (unless (assoc interface (cdr (assoc object result)))
1630 (setcdr
1631 (assoc object result)
1632 (append
1633 (list (cons
1634 interface
1635 ;; We simulate "org.freedesktop.DBus.Properties.GetAll"
1636 ;; by using an appropriate D-Bus event.
1637 (let ((last-input-event
1638 (append
1639 (butlast last-input-event 4)
1640 (list object dbus-interface-properties
1641 "GetAll" 'dbus-property-handler))))
1642 (dbus-property-handler interface))))
1643 (cdr (assoc object result)))))))))
1644 dbus-registered-objects-table)
1645
1646 ;; Return the result, or an empty array.
1647 (list
1648 :array
1649 (or
1650 (mapcar
1651 (lambda (x)
1652 (list
1653 :dict-entry :object-path (car x)
1654 (cons :array (mapcar (lambda (y) (cons :dict-entry y)) (cdr x)))))
1655 result)
1656 '(:signature "{oa{sa{sv}}}"))))))
1657
1045 1658
1046;; Initialize :system and :session buses. This adds their file 1659;; Initialize `:system' and `:session' buses. This adds their file
1047;; descriptors to input_wait_mask, in order to detect incoming 1660;; descriptors to input_wait_mask, in order to detect incoming
1048;; messages immediately. 1661;; messages immediately.
1049(when (featurep 'dbusbind) 1662(when (featurep 'dbusbind)
1050 (dbus-ignore-errors 1663 (dbus-ignore-errors
1051 (dbus-init-bus :system) 1664 (dbus-init-bus :system))
1665 (dbus-ignore-errors
1052 (dbus-init-bus :session))) 1666 (dbus-init-bus :session)))
1053 1667
1054(provide 'dbus) 1668(provide 'dbus)
1055 1669
1670;;; TODO:
1671
1672;; * Implement org.freedesktop.DBus.ObjectManager.InterfacesAdded and
1673;; org.freedesktop.DBus.ObjectManager.InterfacesRemoved.
1674
1056;;; dbus.el ends here 1675;;; dbus.el ends here
diff --git a/src/ChangeLog b/src/ChangeLog
index a1220aeaa7d..205728f91da 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,48 @@
12012-04-22 Michael Albinus <michael.albinus@gmx.de>
2
3 Move functions from C to Lisp. Make non-blocking method calls
4 the default. Implement further D-Bus standard interfaces.
5
6 * dbusbind.c (DBUS_NUM_MESSAGE_TYPES): Declare.
7 (QCdbus_request_name_allow_replacement)
8 (QCdbus_request_name_replace_existing)
9 (QCdbus_request_name_do_not_queue)
10 (QCdbus_request_name_reply_primary_owner)
11 (QCdbus_request_name_reply_in_queue)
12 (QCdbus_request_name_reply_exists)
13 (QCdbus_request_name_reply_already_owner): Move to dbus.el.
14 (QCdbus_registered_serial, QCdbus_registered_method)
15 (QCdbus_registered_signal): New Lisp objects.
16 (XD_DEBUG_MESSAGE): Use sizeof.
17 (XD_MESSAGE_TYPE_TO_STRING, XD_OBJECT_TO_STRING)
18 (XD_DBUS_VALIDATE_BUS_ADDRESS, XD_DBUS_VALIDATE_OBJECT)
19 (XD_DBUS_VALIDATE_BUS_NAME, XD_DBUS_VALIDATE_PATH)
20 (XD_DBUS_VALIDATE_INTERFACE, XD_DBUS_VALIDATE_MEMBER): New macros.
21 (XD_CHECK_DBUS_SERIAL): Rename from CHECK_DBUS_SERIAL_GET_SERIAL.
22 (xd_signature, xd_append_arg): Allow float for integer types.
23 (xd_get_connection_references): New function.
24 (xd_get_connection_address): Rename from xd_initialize. Return
25 cached address.
26 (xd_remove_watch): Do not unset $DBUS_SESSION_BUS_ADDRESS.
27 (xd_close_bus): Rename from Fdbus_close_bus. Not needed on Lisp
28 level.
29 (Fdbus_init_bus): New optional arg PRIVATE. Cache address.
30 Return number of recounts.
31 (Fdbus_get_unique_name): Make stronger parameter check.
32 (Fdbus_message_internal): New defun.
33 (Fdbus_call_method, Fdbus_call_method_asynchronously)
34 (Fdbus_method_return_internal, Fdbus_method_error_internal)
35 (Fdbus_send_signal, Fdbus_register_service)
36 (Fdbus_register_signal, Fdbus_register_method): Move to dbus.el.
37 (xd_read_message_1): Obey new structure of Vdbus_registered_objects.
38 (xd_read_queued_messages): Obey new structure of Vdbus_registered_buses.
39 (Vdbus_compiled_version, Vdbus_runtime_version)
40 (Vdbus_message_type_invalid, Vdbus_message_type_method_call)
41 (Vdbus_message_type_method_return, Vdbus_message_type_error)
42 (Vdbus_message_type_signal): New defvars.
43 (Vdbus_registered_buses, Vdbus_registered_objects_table): Adapt
44 docstring.
45
12012-04-22 Paul Eggert <eggert@cs.ucla.edu> 462012-04-22 Paul Eggert <eggert@cs.ucla.edu>
2 47
3 Fix GC_MALLOC_CHECK debugging output on 64-bit hosts. 48 Fix GC_MALLOC_CHECK debugging output on 64-bit hosts.
diff --git a/src/dbusbind.c b/src/dbusbind.c
index ad1a3f3cbe8..78e5c80baf3 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -28,19 +28,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include "keyboard.h" 28#include "keyboard.h"
29#include "process.h" 29#include "process.h"
30 30
31#ifndef DBUS_NUM_MESSAGE_TYPES
32#define DBUS_NUM_MESSAGE_TYPES 5
33#endif
34
31 35
32/* Subroutines. */ 36/* Subroutines. */
33static Lisp_Object Qdbus_init_bus; 37static Lisp_Object Qdbus_init_bus;
34static Lisp_Object Qdbus_close_bus;
35static Lisp_Object Qdbus_get_unique_name; 38static Lisp_Object Qdbus_get_unique_name;
36static Lisp_Object Qdbus_call_method; 39static Lisp_Object Qdbus_message_internal;
37static Lisp_Object Qdbus_call_method_asynchronously;
38static Lisp_Object Qdbus_method_return_internal;
39static Lisp_Object Qdbus_method_error_internal;
40static Lisp_Object Qdbus_send_signal;
41static Lisp_Object Qdbus_register_service;
42static Lisp_Object Qdbus_register_signal;
43static Lisp_Object Qdbus_register_method;
44 40
45/* D-Bus error symbol. */ 41/* D-Bus error symbol. */
46static Lisp_Object Qdbus_error; 42static Lisp_Object Qdbus_error;
@@ -51,17 +47,6 @@ static Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
51/* Lisp symbol for method call timeout. */ 47/* Lisp symbol for method call timeout. */
52static Lisp_Object QCdbus_timeout; 48static Lisp_Object QCdbus_timeout;
53 49
54/* Lisp symbols for name request flags. */
55static Lisp_Object QCdbus_request_name_allow_replacement;
56static Lisp_Object QCdbus_request_name_replace_existing;
57static Lisp_Object QCdbus_request_name_do_not_queue;
58
59/* Lisp symbols for name request replies. */
60static Lisp_Object QCdbus_request_name_reply_primary_owner;
61static Lisp_Object QCdbus_request_name_reply_in_queue;
62static Lisp_Object QCdbus_request_name_reply_exists;
63static Lisp_Object QCdbus_request_name_reply_already_owner;
64
65/* Lisp symbols of D-Bus types. */ 50/* Lisp symbols of D-Bus types. */
66static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean; 51static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
67static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16; 52static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
@@ -75,6 +60,10 @@ static Lisp_Object QCdbus_type_unix_fd;
75static Lisp_Object QCdbus_type_array, QCdbus_type_variant; 60static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
76static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry; 61static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
77 62
63/* Lisp symbols of objects in `dbus-registered-objects-table'. */
64static Lisp_Object QCdbus_registered_serial, QCdbus_registered_method;
65static Lisp_Object QCdbus_registered_signal;
66
78/* Whether we are reading a D-Bus event. */ 67/* Whether we are reading a D-Bus event. */
79static int xd_in_read_queued_messages = 0; 68static int xd_in_read_queued_messages = 0;
80 69
@@ -120,14 +109,14 @@ static int xd_in_read_queued_messages = 0;
120 } while (0) 109 } while (0)
121 110
122/* Macros for debugging. In order to enable them, build with 111/* Macros for debugging. In order to enable them, build with
123 "MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */ 112 "env MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
124#ifdef DBUS_DEBUG 113#ifdef DBUS_DEBUG
125#define XD_DEBUG_MESSAGE(...) \ 114#define XD_DEBUG_MESSAGE(...) \
126 do { \ 115 do { \
127 char s[1024]; \ 116 char s[1024]; \
128 snprintf (s, sizeof s, __VA_ARGS__); \ 117 snprintf (s, sizeof s, __VA_ARGS__); \
129 printf ("%s: %s\n", __func__, s); \ 118 printf ("%s: %s\n", __func__, s); \
130 message ("%s: %s", __func__, s); \ 119 message ("%s: %s", __func__, s); \
131 } while (0) 120 } while (0)
132#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \ 121#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
133 do { \ 122 do { \
@@ -144,7 +133,7 @@ static int xd_in_read_queued_messages = 0;
144 if (!NILP (Vdbus_debug)) \ 133 if (!NILP (Vdbus_debug)) \
145 { \ 134 { \
146 char s[1024]; \ 135 char s[1024]; \
147 snprintf (s, 1023, __VA_ARGS__); \ 136 snprintf (s, sizeof s, __VA_ARGS__); \
148 message ("%s: %s", __func__, s); \ 137 message ("%s: %s", __func__, s); \
149 } \ 138 } \
150 } while (0) 139 } while (0)
@@ -241,23 +230,112 @@ xd_symbol_to_dbus_type (Lisp_Object object)
241#define XD_NEXT_VALUE(object) \ 230#define XD_NEXT_VALUE(object) \
242 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object) 231 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
243 232
233/* Transform the message type to its string representation for debug
234 messages. */
235#define XD_MESSAGE_TYPE_TO_STRING(mtype) \
236 ((mtype == DBUS_MESSAGE_TYPE_INVALID) \
237 ? "DBUS_MESSAGE_TYPE_INVALID" \
238 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) \
239 ? "DBUS_MESSAGE_TYPE_METHOD_CALL" \
240 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN) \
241 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN" \
242 : (mtype == DBUS_MESSAGE_TYPE_ERROR) \
243 ? "DBUS_MESSAGE_TYPE_ERROR" \
244 : "DBUS_MESSAGE_TYPE_SIGNAL")
245
246/* Transform the object to its string representation for debug
247 messages. */
248#define XD_OBJECT_TO_STRING(object) \
249 SDATA (format2 ("%s", object, Qnil))
250
244/* Check whether X is a valid dbus serial number. If valid, set 251/* Check whether X is a valid dbus serial number. If valid, set
245 SERIAL to its value. Otherwise, signal an error. */ 252 SERIAL to its value. Otherwise, signal an error. */
246#define CHECK_DBUS_SERIAL_GET_SERIAL(x, serial) \ 253#define XD_CHECK_DBUS_SERIAL(x, serial) \
247 do \ 254 do { \
248 { \ 255 dbus_uint32_t DBUS_SERIAL_MAX = -1; \
249 dbus_uint32_t DBUS_SERIAL_MAX = -1; \ 256 if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX) \
250 if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX) \ 257 serial = XINT (x); \
251 serial = XINT (x); \ 258 else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX \
252 else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX \ 259 && FLOATP (x) \
253 && FLOATP (x) \ 260 && 0 <= XFLOAT_DATA (x) \
254 && 0 <= XFLOAT_DATA (x) \ 261 && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX) \
255 && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX) \ 262 serial = XFLOAT_DATA (x); \
256 serial = XFLOAT_DATA (x); \ 263 else \
257 else \ 264 XD_SIGNAL2 (build_string ("Invalid dbus serial"), x); \
258 XD_SIGNAL2 (build_string ("Invalid dbus serial"), x); \ 265 } while (0)
259 } \ 266
260 while (0) 267#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
268 do { \
269 if (STRINGP (bus)) \
270 { \
271 DBusAddressEntry **entries; \
272 int len; \
273 DBusError derror; \
274 dbus_error_init (&derror); \
275 if (!dbus_parse_address (SSDATA (bus), &entries, &len, &derror)) \
276 XD_ERROR (derror); \
277 /* Cleanup. */ \
278 dbus_error_free (&derror); \
279 dbus_address_entries_free (entries); \
280 } \
281 \
282 else \
283 { \
284 CHECK_SYMBOL (bus); \
285 if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus))) \
286 XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \
287 /* We do not want to have an autolaunch for the session bus. */ \
288 if (EQ (bus, QCdbus_session_bus) \
289 && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) \
290 XD_SIGNAL2 (build_string ("No connection to bus"), bus); \
291 } \
292 } while (0)
293
294#define XD_DBUS_VALIDATE_OBJECT(object, func) \
295 do { \
296 if (!NILP (object)) \
297 { \
298 DBusError derror; \
299 CHECK_STRING (object); \
300 dbus_error_init (&derror); \
301 if (!func (SSDATA (object), &derror)) \
302 XD_ERROR (derror); \
303 /* Cleanup. */ \
304 dbus_error_free (&derror); \
305 } \
306 } while (0)
307
308#if HAVE_DBUS_VALIDATE_BUS_NAME
309#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
310 XD_DBUS_VALIDATE_OBJECT(bus_name, dbus_validate_bus_name);
311#else
312#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
313 if (!NILP (bus_name)) CHECK_STRING (bus_name);
314#endif
315
316#if HAVE_DBUS_VALIDATE_PATH
317#define XD_DBUS_VALIDATE_PATH(path) \
318 XD_DBUS_VALIDATE_OBJECT(path, dbus_validate_path);
319#else
320#define XD_DBUS_VALIDATE_PATH(path) \
321 if (!NILP (path)) CHECK_STRING (path);
322#endif
323
324#if HAVE_DBUS_VALIDATE_INTERFACE
325#define XD_DBUS_VALIDATE_INTERFACE(interface) \
326 XD_DBUS_VALIDATE_OBJECT(interface, dbus_validate_interface);
327#else
328#define XD_DBUS_VALIDATE_INTERFACE(interface) \
329 if (!NILP (interface)) CHECK_STRING (interface);
330#endif
331
332#if HAVE_DBUS_VALIDATE_MEMBER
333#define XD_DBUS_VALIDATE_MEMBER(member) \
334 XD_DBUS_VALIDATE_OBJECT(member, dbus_validate_member);
335#else
336#define XD_DBUS_VALIDATE_MEMBER(member) \
337 if (!NILP (member)) CHECK_STRING (member);
338#endif
261 339
262/* Append to SIGNATURE a copy of X, making sure SIGNATURE does 340/* Append to SIGNATURE a copy of X, making sure SIGNATURE does
263 not become too long. */ 341 not become too long. */
@@ -293,11 +371,6 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis
293 { 371 {
294 case DBUS_TYPE_BYTE: 372 case DBUS_TYPE_BYTE:
295 case DBUS_TYPE_UINT16: 373 case DBUS_TYPE_UINT16:
296 case DBUS_TYPE_UINT32:
297 case DBUS_TYPE_UINT64:
298#ifdef DBUS_TYPE_UNIX_FD
299 case DBUS_TYPE_UNIX_FD:
300#endif
301 CHECK_NATNUM (object); 374 CHECK_NATNUM (object);
302 sprintf (signature, "%c", dtype); 375 sprintf (signature, "%c", dtype);
303 break; 376 break;
@@ -309,14 +382,19 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis
309 break; 382 break;
310 383
311 case DBUS_TYPE_INT16: 384 case DBUS_TYPE_INT16:
312 case DBUS_TYPE_INT32:
313 case DBUS_TYPE_INT64:
314 CHECK_NUMBER (object); 385 CHECK_NUMBER (object);
315 sprintf (signature, "%c", dtype); 386 sprintf (signature, "%c", dtype);
316 break; 387 break;
317 388
389 case DBUS_TYPE_UINT32:
390 case DBUS_TYPE_UINT64:
391#ifdef DBUS_TYPE_UNIX_FD
392 case DBUS_TYPE_UNIX_FD:
393#endif
394 case DBUS_TYPE_INT32:
395 case DBUS_TYPE_INT64:
318 case DBUS_TYPE_DOUBLE: 396 case DBUS_TYPE_DOUBLE:
319 CHECK_FLOAT (object); 397 CHECK_NUMBER_OR_FLOAT (object);
320 sprintf (signature, "%c", dtype); 398 sprintf (signature, "%c", dtype);
321 break; 399 break;
322 400
@@ -352,8 +430,8 @@ xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lis
352 } 430 }
353 431
354 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the 432 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
355 only element, the value of this element is used as he array's 433 only element, the value of this element is used as the
356 element signature. */ 434 array's element signature. */
357 if ((subtype == DBUS_TYPE_SIGNATURE) 435 if ((subtype == DBUS_TYPE_SIGNATURE)
358 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt))) 436 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
359 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt)))) 437 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
@@ -505,9 +583,8 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
505 } 583 }
506 584
507 case DBUS_TYPE_INT32: 585 case DBUS_TYPE_INT32:
508 CHECK_NUMBER (object);
509 { 586 {
510 dbus_int32_t val = XINT (object); 587 dbus_int32_t val = extract_float (object);
511 XD_DEBUG_MESSAGE ("%c %d", dtype, val); 588 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
512 if (!dbus_message_iter_append_basic (iter, dtype, &val)) 589 if (!dbus_message_iter_append_basic (iter, dtype, &val))
513 XD_SIGNAL2 (build_string ("Unable to append argument"), object); 590 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -518,9 +595,8 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
518#ifdef DBUS_TYPE_UNIX_FD 595#ifdef DBUS_TYPE_UNIX_FD
519 case DBUS_TYPE_UNIX_FD: 596 case DBUS_TYPE_UNIX_FD:
520#endif 597#endif
521 CHECK_NATNUM (object);
522 { 598 {
523 dbus_uint32_t val = XFASTINT (object); 599 dbus_uint32_t val = extract_float (object);
524 XD_DEBUG_MESSAGE ("%c %u", dtype, val); 600 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
525 if (!dbus_message_iter_append_basic (iter, dtype, &val)) 601 if (!dbus_message_iter_append_basic (iter, dtype, &val))
526 XD_SIGNAL2 (build_string ("Unable to append argument"), object); 602 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -528,9 +604,8 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
528 } 604 }
529 605
530 case DBUS_TYPE_INT64: 606 case DBUS_TYPE_INT64:
531 CHECK_NUMBER (object);
532 { 607 {
533 dbus_int64_t val = XINT (object); 608 dbus_int64_t val = extract_float (object);
534 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val); 609 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
535 if (!dbus_message_iter_append_basic (iter, dtype, &val)) 610 if (!dbus_message_iter_append_basic (iter, dtype, &val))
536 XD_SIGNAL2 (build_string ("Unable to append argument"), object); 611 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -538,19 +613,17 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
538 } 613 }
539 614
540 case DBUS_TYPE_UINT64: 615 case DBUS_TYPE_UINT64:
541 CHECK_NATNUM (object);
542 { 616 {
543 dbus_uint64_t val = XFASTINT (object); 617 dbus_uint64_t val = extract_float (object);
544 XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, XFASTINT (object)); 618 XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, val);
545 if (!dbus_message_iter_append_basic (iter, dtype, &val)) 619 if (!dbus_message_iter_append_basic (iter, dtype, &val))
546 XD_SIGNAL2 (build_string ("Unable to append argument"), object); 620 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
547 return; 621 return;
548 } 622 }
549 623
550 case DBUS_TYPE_DOUBLE: 624 case DBUS_TYPE_DOUBLE:
551 CHECK_FLOAT (object);
552 { 625 {
553 double val = XFLOAT_DATA (object); 626 double val = extract_float (object);
554 XD_DEBUG_MESSAGE ("%c %f", dtype, val); 627 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
555 if (!dbus_message_iter_append_basic (iter, dtype, &val)) 628 if (!dbus_message_iter_append_basic (iter, dtype, &val))
556 XD_SIGNAL2 (build_string ("Unable to append argument"), object); 629 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
@@ -614,7 +687,7 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
614 dtype, CAR_SAFE (XD_NEXT_VALUE (object))); 687 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
615 688
616 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature, 689 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
617 SDATA (format2 ("%s", object, Qnil))); 690 XD_OBJECT_TO_STRING (object));
618 if (!dbus_message_iter_open_container (iter, dtype, 691 if (!dbus_message_iter_open_container (iter, dtype,
619 signature, &subiter)) 692 signature, &subiter))
620 XD_SIGNAL3 (build_string ("Cannot open container"), 693 XD_SIGNAL3 (build_string ("Cannot open container"),
@@ -627,7 +700,7 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
627 dtype, CAR_SAFE (XD_NEXT_VALUE (object))); 700 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
628 701
629 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature, 702 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
630 SDATA (format2 ("%s", object, Qnil))); 703 XD_OBJECT_TO_STRING (object));
631 if (!dbus_message_iter_open_container (iter, dtype, 704 if (!dbus_message_iter_open_container (iter, dtype,
632 signature, &subiter)) 705 signature, &subiter))
633 XD_SIGNAL3 (build_string ("Cannot open container"), 706 XD_SIGNAL3 (build_string ("Cannot open container"),
@@ -637,8 +710,7 @@ xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
637 case DBUS_TYPE_STRUCT: 710 case DBUS_TYPE_STRUCT:
638 case DBUS_TYPE_DICT_ENTRY: 711 case DBUS_TYPE_DICT_ENTRY:
639 /* These containers do not require a signature. */ 712 /* These containers do not require a signature. */
640 XD_DEBUG_MESSAGE ("%c %s", dtype, 713 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (object));
641 SDATA (format2 ("%s", object, Qnil)));
642 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter)) 714 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
643 XD_SIGNAL2 (build_string ("Cannot open container"), 715 XD_SIGNAL2 (build_string ("Cannot open container"),
644 make_number (dtype)); 716 make_number (dtype));
@@ -777,7 +849,7 @@ xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
777 result = Fcons (xd_retrieve_arg (subtype, &subiter), result); 849 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
778 dbus_message_iter_next (&subiter); 850 dbus_message_iter_next (&subiter);
779 } 851 }
780 XD_DEBUG_MESSAGE ("%c %s", dtype, SDATA (format2 ("%s", result, Qnil))); 852 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (result));
781 RETURN_UNGCPRO (Fnreverse (result)); 853 RETURN_UNGCPRO (Fnreverse (result));
782 } 854 }
783 855
@@ -787,85 +859,37 @@ xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
787 } 859 }
788} 860}
789 861
790/* Initialize D-Bus connection. BUS is either a Lisp symbol, :system 862/* Return the number of references of the shared CONNECTION. */
791 or :session, or a string denoting the bus address. It tells which 863static int
792 D-Bus to initialize. If RAISE_ERROR is non-zero, signal an error 864xd_get_connection_references (DBusConnection *connection)
793 when the connection cannot be initialized. */ 865{
866 ptrdiff_t *refcount;
867
868 /* We cannot access the DBusConnection structure, it is not public.
869 But we know, that the reference counter is the first field in
870 that structure. */
871 refcount = (void *) &connection;
872 refcount = (void *) *refcount;
873 return *refcount;
874}
875
876/* Return D-Bus connection address. BUS is either a Lisp symbol,
877 :system or :session, or a string denoting the bus address. */
794static DBusConnection * 878static DBusConnection *
795xd_initialize (Lisp_Object bus, int raise_error) 879xd_get_connection_address (Lisp_Object bus)
796{ 880{
797 DBusConnection *connection; 881 DBusConnection *connection;
798 DBusError derror; 882 Lisp_Object val;
799
800 /* Parameter check. */
801 if (!STRINGP (bus))
802 {
803 CHECK_SYMBOL (bus);
804 if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus)))
805 {
806 if (raise_error)
807 XD_SIGNAL2 (build_string ("Wrong bus name"), bus);
808 else
809 return NULL;
810 }
811 883
812 /* We do not want to have an autolaunch for the session bus. */ 884 val = CDR_SAFE (Fassoc (bus, Vdbus_registered_buses));
813 if (EQ (bus, QCdbus_session_bus) 885 if (NILP (val))
814 && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) 886 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
815 {
816 if (raise_error)
817 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
818 else
819 return NULL;
820 }
821 }
822
823 /* Open a connection to the bus. */
824 dbus_error_init (&derror);
825
826 if (STRINGP (bus))
827 connection = dbus_connection_open (SSDATA (bus), &derror);
828 else 887 else
829 if (EQ (bus, QCdbus_system_bus)) 888 connection = (DBusConnection *) XFASTINT (val);
830 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
831 else
832 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
833
834 if (dbus_error_is_set (&derror))
835 {
836 if (raise_error)
837 XD_ERROR (derror);
838 else
839 connection = NULL;
840 }
841
842 /* If it is not the system or session bus, we must register
843 ourselves. Otherwise, we have called dbus_bus_get, which has
844 configured us to exit if the connection closes - we undo this
845 setting. */
846 if (connection != NULL)
847 {
848 if (STRINGP (bus))
849 dbus_bus_register (connection, &derror);
850 else
851 dbus_connection_set_exit_on_disconnect (connection, FALSE);
852 }
853
854 if (dbus_error_is_set (&derror))
855 {
856 if (raise_error)
857 XD_ERROR (derror);
858 else
859 connection = NULL;
860 }
861 889
862 if (connection == NULL && raise_error) 890 if (!dbus_connection_get_is_connected (connection))
863 XD_SIGNAL2 (build_string ("No connection to bus"), bus); 891 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
864 892
865 /* Cleanup. */
866 dbus_error_free (&derror);
867
868 /* Return the result. */
869 return connection; 893 return connection;
870} 894}
871 895
@@ -896,8 +920,8 @@ xd_add_watch (DBusWatch *watch, void *data)
896 int fd = xd_find_watch_fd (watch); 920 int fd = xd_find_watch_fd (watch);
897 921
898 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d", 922 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
899 fd, flags & DBUS_WATCH_WRITABLE, 923 fd, flags & DBUS_WATCH_WRITABLE,
900 dbus_watch_get_enabled (watch)); 924 dbus_watch_get_enabled (watch));
901 925
902 if (fd == -1) 926 if (fd == -1)
903 return FALSE; 927 return FALSE;
@@ -929,8 +953,8 @@ xd_remove_watch (DBusWatch *watch, void *data)
929 /* Unset session environment. */ 953 /* Unset session environment. */
930 if (XSYMBOL (QCdbus_session_bus) == data) 954 if (XSYMBOL (QCdbus_session_bus) == data)
931 { 955 {
932 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); 956 // XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
933 unsetenv ("DBUS_SESSION_BUS_ADDRESS"); 957 // unsetenv ("DBUS_SESSION_BUS_ADDRESS");
934 } 958 }
935 959
936 if (flags & DBUS_WATCH_WRITABLE) 960 if (flags & DBUS_WATCH_WRITABLE)
@@ -949,23 +973,111 @@ xd_toggle_watch (DBusWatch *watch, void *data)
949 xd_remove_watch (watch, data); 973 xd_remove_watch (watch, data);
950} 974}
951 975
952DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0, 976/* Close connection to D-Bus BUS. */
953 doc: /* Initialize connection to D-Bus BUS. */) 977static void
954 (Lisp_Object bus) 978xd_close_bus (Lisp_Object bus)
979{
980 DBusConnection *connection;
981 Lisp_Object val;
982
983 /* Check whether we are connected. */
984 val = Fassoc (bus, Vdbus_registered_buses);
985 if (NILP (val))
986 return;
987
988 /* Retrieve bus address. */
989 connection = xd_get_connection_address (bus);
990
991 /* Close connection, if there isn't another shared application. */
992 if (xd_get_connection_references (connection) == 1)
993 {
994 XD_DEBUG_MESSAGE ("Close connection to bus %s",
995 XD_OBJECT_TO_STRING (bus));
996 dbus_connection_close (connection);
997 }
998
999 /* Decrement reference count. */
1000 dbus_connection_unref (connection);
1001
1002 /* Remove bus from list of registered buses. */
1003 Vdbus_registered_buses = Fdelete (val, Vdbus_registered_buses);
1004
1005 /* Return. */
1006 return;
1007}
1008
1009DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 2, 0,
1010 doc: /* Establish the connection to D-Bus BUS.
1011
1012BUS can be either the symbol `:system' or the symbol `:session', or it
1013can be a string denoting the address of the corresponding bus. For
1014the system and session buses, this function is called when loading
1015`dbus.el', there is no need to call it again.
1016
1017The function returns a number, which counts the connections this Emacs
1018session has established to the BUS under the same unique name (see
1019`dbus-get-unique-name'). It depends on the libraries Emacs is linked
1020with, and on the environment Emacs is running. For example, if Emacs
1021is linked with the gtk toolkit, and it runs in a GTK-aware environment
1022like Gnome, another connection might already be established.
1023
1024When PRIVATE is non-nil, a new connection is established instead of
1025reusing an existing one. It results in a new unique name at the bus.
1026This can be used, if it is necessary to distinguish from another
1027connection used in the same Emacs process, like the one established by
1028GTK+. It should be used with care for at least the `:system' and
1029`:session' buses, because other Emacs Lisp packages might already use
1030this connection to those buses. */)
1031 (Lisp_Object bus, Lisp_Object private)
955{ 1032{
956 DBusConnection *connection; 1033 DBusConnection *connection;
957 void *busp; 1034 DBusError derror;
1035 Lisp_Object val;
1036 int refcount;
958 1037
959 /* Check parameter. */ 1038 /* Check parameter. */
960 if (SYMBOLP (bus)) 1039 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
961 busp = XSYMBOL (bus); 1040
962 else if (STRINGP (bus)) 1041 /* Close bus if it is already open. */
963 busp = XSTRING (bus); 1042 xd_close_bus (bus);
1043
1044 /* Initialize. */
1045 dbus_error_init (&derror);
1046
1047 /* Open the connection. */
1048 if (STRINGP (bus))
1049 if (NILP (private))
1050 connection = dbus_connection_open (SSDATA (bus), &derror);
1051 else
1052 connection = dbus_connection_open_private (SSDATA (bus), &derror);
1053
964 else 1054 else
965 wrong_type_argument (intern ("D-Bus"), bus); 1055 if (NILP (private))
1056 connection = dbus_bus_get (EQ (bus, QCdbus_system_bus)
1057 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1058 &derror);
1059 else
1060 connection = dbus_bus_get_private (EQ (bus, QCdbus_system_bus)
1061 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1062 &derror);
1063
1064 if (dbus_error_is_set (&derror))
1065 XD_ERROR (derror);
966 1066
967 /* Open a connection to the bus. */ 1067 if (connection == NULL)
968 connection = xd_initialize (bus, TRUE); 1068 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
1069
1070 /* If it is not the system or session bus, we must register
1071 ourselves. Otherwise, we have called dbus_bus_get, which has
1072 configured us to exit if the connection closes - we undo this
1073 setting. */
1074 if (STRINGP (bus))
1075 dbus_bus_register (connection, &derror);
1076 else
1077 dbus_connection_set_exit_on_disconnect (connection, FALSE);
1078
1079 if (dbus_error_is_set (&derror))
1080 XD_ERROR (derror);
969 1081
970 /* Add the watch functions. We pass also the bus as data, in order 1082 /* Add the watch functions. We pass also the bus as data, in order
971 to distinguish between the buses in xd_remove_watch. */ 1083 to distinguish between the buses in xd_remove_watch. */
@@ -973,36 +1085,27 @@ DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
973 xd_add_watch, 1085 xd_add_watch,
974 xd_remove_watch, 1086 xd_remove_watch,
975 xd_toggle_watch, 1087 xd_toggle_watch,
976 busp, NULL)) 1088 SYMBOLP (bus)
1089 ? (void *) XSYMBOL (bus)
1090 : (void *) XSTRING (bus),
1091 NULL))
977 XD_SIGNAL1 (build_string ("Cannot add watch functions")); 1092 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
978 1093
979 /* Add bus to list of registered buses. */ 1094 /* Add bus to list of registered buses. */
980 Vdbus_registered_buses = Fcons (bus, Vdbus_registered_buses); 1095 XSETFASTINT (val, connection);
1096 Vdbus_registered_buses = Fcons (Fcons (bus, val), Vdbus_registered_buses);
981 1097
982 /* We do not want to abort. */ 1098 /* We do not want to abort. */
983 putenv ((char *) "DBUS_FATAL_WARNINGS=0"); 1099 putenv ((char *) "DBUS_FATAL_WARNINGS=0");
984 1100
985 /* Return. */ 1101 /* Cleanup. */
986 return Qnil; 1102 dbus_error_free (&derror);
987}
988
989DEFUN ("dbus-close-bus", Fdbus_close_bus, Sdbus_close_bus, 1, 1, 0,
990 doc: /* Close connection to D-Bus BUS. */)
991 (Lisp_Object bus)
992{
993 DBusConnection *connection;
994
995 /* Open a connection to the bus. */
996 connection = xd_initialize (bus, TRUE);
997
998 /* Decrement reference count to the bus. */
999 dbus_connection_unref (connection);
1000
1001 /* Remove bus from list of registered buses. */
1002 Vdbus_registered_buses = Fdelete (bus, Vdbus_registered_buses);
1003 1103
1004 /* Return. */ 1104 /* Return reference counter. */
1005 return Qnil; 1105 refcount = xd_get_connection_references (connection);
1106 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %d",
1107 XD_OBJECT_TO_STRING (bus), refcount);
1108 return make_number (refcount);
1006} 1109}
1007 1110
1008DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name, 1111DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
@@ -1013,8 +1116,11 @@ DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
1013 DBusConnection *connection; 1116 DBusConnection *connection;
1014 const char *name; 1117 const char *name;
1015 1118
1016 /* Open a connection to the bus. */ 1119 /* Check parameter. */
1017 connection = xd_initialize (bus, TRUE); 1120 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1121
1122 /* Retrieve bus address. */
1123 connection = xd_get_connection_address (bus);
1018 1124
1019 /* Request the name. */ 1125 /* Request the name. */
1020 name = dbus_bus_get_unique_name (connection); 1126 name = dbus_bus_get_unique_name (connection);
@@ -1025,341 +1131,241 @@ DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
1025 return build_string (name); 1131 return build_string (name);
1026} 1132}
1027 1133
1028DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0, 1134DEFUN ("dbus-message-internal", Fdbus_message_internal, Sdbus_message_internal,
1029 doc: /* Call METHOD on the D-Bus BUS. 1135 4, MANY, 0,
1030 1136 doc: /* Send a D-Bus message.
1031BUS is either a Lisp symbol, `:system' or `:session', or a string 1137This is an internal function, it shall not be used outside dbus.el.
1032denoting the bus address. 1138
1033 1139The following usages are expected:
1034SERVICE is the D-Bus service name to be used. PATH is the D-Bus 1140
1035object path SERVICE is registered at. INTERFACE is an interface 1141`dbus-call-method', `dbus-call-method-asynchronously':
1036offered by SERVICE. It must provide METHOD. 1142 \(dbus-message-internal
1037 1143 dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER
1038If the parameter `:timeout' is given, the following integer TIMEOUT 1144 &optional :timeout TIMEOUT &rest ARGS)
1039specifies the maximum number of milliseconds the method call must 1145
1040return. The default value is 25,000. If the method call doesn't 1146`dbus-send-signal':
1041return in time, a D-Bus error is raised. 1147 \(dbus-message-internal
1042 1148 dbus-message-type-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)
1043All other arguments ARGS are passed to METHOD as arguments. They are 1149
1044converted into D-Bus types via the following rules: 1150`dbus-method-return-internal':
1045 1151 \(dbus-message-internal
1046 t and nil => DBUS_TYPE_BOOLEAN 1152 dbus-message-type-method-return BUS SERVICE SERIAL &rest ARGS)
1047 number => DBUS_TYPE_UINT32 1153
1048 integer => DBUS_TYPE_INT32 1154`dbus-method-error-internal':
1049 float => DBUS_TYPE_DOUBLE 1155 \(dbus-message-internal
1050 string => DBUS_TYPE_STRING 1156 dbus-message-type-error BUS SERVICE SERIAL &rest ARGS)
1051 list => DBUS_TYPE_ARRAY 1157
1052 1158usage: (dbus-message-internal &rest REST) */)
1053All arguments can be preceded by a type symbol. For details about
1054type symbols, see Info node `(dbus)Type Conversion'.
1055
1056`dbus-call-method' returns the resulting values of METHOD as a list of
1057Lisp objects. The type conversion happens the other direction as for
1058input arguments. It follows the mapping rules:
1059
1060 DBUS_TYPE_BOOLEAN => t or nil
1061 DBUS_TYPE_BYTE => number
1062 DBUS_TYPE_UINT16 => number
1063 DBUS_TYPE_INT16 => integer
1064 DBUS_TYPE_UINT32 => number or float
1065 DBUS_TYPE_UNIX_FD => number or float
1066 DBUS_TYPE_INT32 => integer or float
1067 DBUS_TYPE_UINT64 => number or float
1068 DBUS_TYPE_INT64 => integer or float
1069 DBUS_TYPE_DOUBLE => float
1070 DBUS_TYPE_STRING => string
1071 DBUS_TYPE_OBJECT_PATH => string
1072 DBUS_TYPE_SIGNATURE => string
1073 DBUS_TYPE_ARRAY => list
1074 DBUS_TYPE_VARIANT => list
1075 DBUS_TYPE_STRUCT => list
1076 DBUS_TYPE_DICT_ENTRY => list
1077
1078Example:
1079
1080\(dbus-call-method
1081 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
1082 "org.gnome.seahorse.Keys" "GetKeyField"
1083 "openpgp:657984B8C7A966DD" "simple-name")
1084
1085 => (t ("Philip R. Zimmermann"))
1086
1087If the result of the METHOD call is just one value, the converted Lisp
1088object is returned instead of a list containing this single Lisp object.
1089
1090\(dbus-call-method
1091 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1092 "org.freedesktop.Hal.Device" "GetPropertyString"
1093 "system.kernel.machine")
1094
1095 => "i686"
1096
1097usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TIMEOUT &rest ARGS) */)
1098 (ptrdiff_t nargs, Lisp_Object *args) 1159 (ptrdiff_t nargs, Lisp_Object *args)
1099{ 1160{
1100 Lisp_Object bus, service, path, interface, method; 1161 Lisp_Object message_type, bus, service, handler;
1162 Lisp_Object path = Qnil;
1163 Lisp_Object interface = Qnil;
1164 Lisp_Object member = Qnil;
1101 Lisp_Object result; 1165 Lisp_Object result;
1102 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 1166 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1103 DBusConnection *connection; 1167 DBusConnection *connection;
1104 DBusMessage *dmessage; 1168 DBusMessage *dmessage;
1105 DBusMessage *reply;
1106 DBusMessageIter iter; 1169 DBusMessageIter iter;
1107 DBusError derror;
1108 unsigned int dtype; 1170 unsigned int dtype;
1171 unsigned int mtype;
1172 dbus_uint32_t serial = 0;
1109 int timeout = -1; 1173 int timeout = -1;
1110 ptrdiff_t i = 5; 1174 ptrdiff_t count;
1111 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; 1175 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1112 1176
1177 /* Initialize parameters. */
1178 message_type = args[0];
1179 bus = args[1];
1180 service = args[2];
1181 handler = Qnil;
1182
1183 CHECK_NATNUM (message_type);
1184 mtype = XFASTINT (message_type);
1185 if ((mtype <= DBUS_MESSAGE_TYPE_INVALID) || (mtype >= DBUS_NUM_MESSAGE_TYPES))
1186 XD_SIGNAL2 (build_string ("Invalid message type"), message_type);
1187
1188 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1189 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1190 {
1191 path = args[3];
1192 interface = args[4];
1193 member = args[5];
1194 if (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1195 handler = args[6];
1196 count = (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) ? 7 : 6;
1197 }
1198 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1199 {
1200 XD_CHECK_DBUS_SERIAL (args[3], serial);
1201 count = 4;
1202 }
1203
1113 /* Check parameters. */ 1204 /* Check parameters. */
1114 bus = args[0]; 1205 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1115 service = args[1]; 1206 XD_DBUS_VALIDATE_BUS_NAME (service);
1116 path = args[2]; 1207 if (nargs < count)
1117 interface = args[3]; 1208 xsignal2 (Qwrong_number_of_arguments,
1118 method = args[4]; 1209 Qdbus_message_internal,
1119 1210 make_number (nargs));
1120 CHECK_STRING (service); 1211
1121 CHECK_STRING (path); 1212 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1122 CHECK_STRING (interface); 1213 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1123 CHECK_STRING (method); 1214 {
1124 GCPRO5 (bus, service, path, interface, method); 1215 XD_DBUS_VALIDATE_PATH (path);
1125 1216 XD_DBUS_VALIDATE_INTERFACE (interface);
1126 XD_DEBUG_MESSAGE ("%s %s %s %s", 1217 XD_DBUS_VALIDATE_MEMBER (member);
1127 SDATA (service), 1218 if (!NILP (handler) && (!FUNCTIONP (handler)))
1128 SDATA (path), 1219 wrong_type_argument (Qinvalid_function, handler);
1129 SDATA (interface), 1220 }
1130 SDATA (method));
1131
1132 /* Open a connection to the bus. */
1133 connection = xd_initialize (bus, TRUE);
1134
1135 /* Create the message. */
1136 dmessage = dbus_message_new_method_call (SSDATA (service),
1137 SSDATA (path),
1138 SSDATA (interface),
1139 SSDATA (method));
1140 UNGCPRO;
1141 if (dmessage == NULL)
1142 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1143 1221
1144 /* Check for timeout parameter. */ 1222 /* Protect Lisp variables. */
1145 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout))) 1223 GCPRO6 (bus, service, path, interface, member, handler);
1224
1225 /* Trace parameters. */
1226 switch (mtype)
1146 { 1227 {
1147 CHECK_NATNUM (args[i+1]); 1228 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1148 timeout = XFASTINT (args[i+1]); 1229 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s %s",
1149 i = i+2; 1230 XD_MESSAGE_TYPE_TO_STRING (mtype),
1231 XD_OBJECT_TO_STRING (bus),
1232 XD_OBJECT_TO_STRING (service),
1233 XD_OBJECT_TO_STRING (path),
1234 XD_OBJECT_TO_STRING (interface),
1235 XD_OBJECT_TO_STRING (member),
1236 XD_OBJECT_TO_STRING (handler));
1237 break;
1238 case DBUS_MESSAGE_TYPE_SIGNAL:
1239 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s",
1240 XD_MESSAGE_TYPE_TO_STRING (mtype),
1241 XD_OBJECT_TO_STRING (bus),
1242 XD_OBJECT_TO_STRING (service),
1243 XD_OBJECT_TO_STRING (path),
1244 XD_OBJECT_TO_STRING (interface),
1245 XD_OBJECT_TO_STRING (member));
1246 break;
1247 default: /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1248 XD_DEBUG_MESSAGE ("%s %s %s %u",
1249 XD_MESSAGE_TYPE_TO_STRING (mtype),
1250 XD_OBJECT_TO_STRING (bus),
1251 XD_OBJECT_TO_STRING (service),
1252 serial);
1150 } 1253 }
1151 1254
1152 /* Initialize parameter list of message. */ 1255 /* Retrieve bus address. */
1153 dbus_message_iter_init_append (dmessage, &iter); 1256 connection = xd_get_connection_address (bus);
1154 1257
1155 /* Append parameters to the message. */ 1258 /* Create the D-Bus message. */
1156 for (; i < nargs; ++i) 1259 dmessage = dbus_message_new (mtype);
1260 if (dmessage == NULL)
1157 { 1261 {
1158 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]); 1262 UNGCPRO;
1159 if (XD_DBUS_TYPE_P (args[i])) 1263 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1264 }
1265
1266 if (STRINGP (service))
1267 {
1268 if (mtype != DBUS_MESSAGE_TYPE_SIGNAL)
1269 /* Set destination. */
1160 { 1270 {
1161 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]); 1271 if (!dbus_message_set_destination (dmessage, SSDATA (service)))
1162 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]); 1272 {
1163 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4, 1273 UNGCPRO;
1164 SDATA (format2 ("%s", args[i], Qnil)), 1274 XD_SIGNAL2 (build_string ("Unable to set the destination"),
1165 SDATA (format2 ("%s", args[i+1], Qnil))); 1275 service);
1166 ++i; 1276 }
1167 } 1277 }
1278
1168 else 1279 else
1280 /* Set destination for unicast signals. */
1169 { 1281 {
1170 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]); 1282 Lisp_Object uname;
1171 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4,
1172 SDATA (format2 ("%s", args[i], Qnil)));
1173 }
1174 1283
1175 /* Check for valid signature. We use DBUS_TYPE_INVALID as 1284 /* If it is the same unique name as we are registered at the
1176 indication that there is no parent type. */ 1285 bus or an unknown name, we regard it as broadcast message
1177 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]); 1286 due to backward compatibility. */
1287 if (dbus_bus_name_has_owner (connection, SSDATA (service), NULL))
1288 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1289 else
1290 uname = Qnil;
1178 1291
1179 xd_append_arg (dtype, args[i], &iter); 1292 if (STRINGP (uname)
1293 && (strcmp (dbus_bus_get_unique_name (connection), SSDATA (uname))
1294 != 0)
1295 && (!dbus_message_set_destination (dmessage, SSDATA (service))))
1296 {
1297 UNGCPRO;
1298 XD_SIGNAL2 (build_string ("Unable to set signal destination"),
1299 service);
1300 }
1301 }
1180 } 1302 }
1181 1303
1182 /* Send the message. */ 1304 /* Set message parameters. */
1183 dbus_error_init (&derror); 1305 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1184 reply = dbus_connection_send_with_reply_and_block (connection, 1306 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1185 dmessage,
1186 timeout,
1187 &derror);
1188
1189 if (dbus_error_is_set (&derror))
1190 XD_ERROR (derror);
1191
1192 if (reply == NULL)
1193 XD_SIGNAL1 (build_string ("No reply"));
1194
1195 XD_DEBUG_MESSAGE ("Message sent");
1196
1197 /* Collect the results. */
1198 result = Qnil;
1199 GCPRO1 (result);
1200
1201 if (dbus_message_iter_init (reply, &iter))
1202 { 1307 {
1203 /* Loop over the parameters of the D-Bus reply message. Construct a 1308 if ((!dbus_message_set_path (dmessage, SSDATA (path)))
1204 Lisp list, which is returned by `dbus-call-method'. */ 1309 || (!dbus_message_set_interface (dmessage, SSDATA (interface)))
1205 while ((dtype = dbus_message_iter_get_arg_type (&iter)) 1310 || (!dbus_message_set_member (dmessage, SSDATA (member))))
1206 != DBUS_TYPE_INVALID)
1207 { 1311 {
1208 result = Fcons (xd_retrieve_arg (dtype, &iter), result); 1312 UNGCPRO;
1209 dbus_message_iter_next (&iter); 1313 XD_SIGNAL1 (build_string ("Unable to set the message parameter"));
1210 } 1314 }
1211 } 1315 }
1212 else
1213 {
1214 /* No arguments: just return nil. */
1215 }
1216
1217 /* Cleanup. */
1218 dbus_error_free (&derror);
1219 dbus_message_unref (dmessage);
1220 dbus_message_unref (reply);
1221
1222 /* Return the result. If there is only one single Lisp object,
1223 return it as-it-is, otherwise return the reversed list. */
1224 if (XFASTINT (Flength (result)) == 1)
1225 RETURN_UNGCPRO (CAR_SAFE (result));
1226 else
1227 RETURN_UNGCPRO (Fnreverse (result));
1228}
1229
1230DEFUN ("dbus-call-method-asynchronously", Fdbus_call_method_asynchronously,
1231 Sdbus_call_method_asynchronously, 6, MANY, 0,
1232 doc: /* Call METHOD on the D-Bus BUS asynchronously.
1233
1234BUS is either a Lisp symbol, `:system' or `:session', or a string
1235denoting the bus address.
1236
1237SERVICE is the D-Bus service name to be used. PATH is the D-Bus
1238object path SERVICE is registered at. INTERFACE is an interface
1239offered by SERVICE. It must provide METHOD.
1240
1241HANDLER is a Lisp function, which is called when the corresponding
1242return message has arrived. If HANDLER is nil, no return message will
1243be expected.
1244 1316
1245If the parameter `:timeout' is given, the following integer TIMEOUT 1317 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1246specifies the maximum number of milliseconds the method call must 1318 {
1247return. The default value is 25,000. If the method call doesn't 1319 if (!dbus_message_set_reply_serial (dmessage, serial))
1248return in time, a D-Bus error is raised. 1320 {
1249 1321 UNGCPRO;
1250All other arguments ARGS are passed to METHOD as arguments. They are 1322 XD_SIGNAL1 (build_string ("Unable to create a return message"));
1251converted into D-Bus types via the following rules: 1323 }
1252
1253 t and nil => DBUS_TYPE_BOOLEAN
1254 number => DBUS_TYPE_UINT32
1255 integer => DBUS_TYPE_INT32
1256 float => DBUS_TYPE_DOUBLE
1257 string => DBUS_TYPE_STRING
1258 list => DBUS_TYPE_ARRAY
1259
1260All arguments can be preceded by a type symbol. For details about
1261type symbols, see Info node `(dbus)Type Conversion'.
1262
1263Unless HANDLER is nil, the function returns a key into the hash table
1264`dbus-registered-objects-table'. The corresponding entry in the hash
1265table is removed, when the return message has been arrived, and
1266HANDLER is called.
1267
1268Example:
1269
1270\(dbus-call-method-asynchronously
1271 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1272 "org.freedesktop.Hal.Device" "GetPropertyString" 'message
1273 "system.kernel.machine")
1274
1275 => (:system 2)
1276
1277 -| i686
1278
1279usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLER &optional :timeout TIMEOUT &rest ARGS) */)
1280 (ptrdiff_t nargs, Lisp_Object *args)
1281{
1282 Lisp_Object bus, service, path, interface, method, handler;
1283 Lisp_Object result;
1284 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1285 DBusConnection *connection;
1286 DBusMessage *dmessage;
1287 DBusMessageIter iter;
1288 unsigned int dtype;
1289 dbus_uint32_t serial;
1290 int timeout = -1;
1291 ptrdiff_t i = 6;
1292 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1293 1324
1294 /* Check parameters. */ 1325 if ((mtype == DBUS_MESSAGE_TYPE_ERROR)
1295 bus = args[0]; 1326 && (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED)))
1296 service = args[1]; 1327 {
1297 path = args[2]; 1328 UNGCPRO;
1298 interface = args[3]; 1329 XD_SIGNAL1 (build_string ("Unable to create a error message"));
1299 method = args[4]; 1330 }
1300 handler = args[5]; 1331 }
1301
1302 CHECK_STRING (service);
1303 CHECK_STRING (path);
1304 CHECK_STRING (interface);
1305 CHECK_STRING (method);
1306 if (!NILP (handler) && !FUNCTIONP (handler))
1307 wrong_type_argument (Qinvalid_function, handler);
1308 GCPRO6 (bus, service, path, interface, method, handler);
1309
1310 XD_DEBUG_MESSAGE ("%s %s %s %s",
1311 SDATA (service),
1312 SDATA (path),
1313 SDATA (interface),
1314 SDATA (method));
1315
1316 /* Open a connection to the bus. */
1317 connection = xd_initialize (bus, TRUE);
1318
1319 /* Create the message. */
1320 dmessage = dbus_message_new_method_call (SSDATA (service),
1321 SSDATA (path),
1322 SSDATA (interface),
1323 SSDATA (method));
1324 if (dmessage == NULL)
1325 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1326 1332
1327 /* Check for timeout parameter. */ 1333 /* Check for timeout parameter. */
1328 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout))) 1334 if ((count+2 <= nargs) && (EQ ((args[count]), QCdbus_timeout)))
1329 { 1335 {
1330 CHECK_NATNUM (args[i+1]); 1336 CHECK_NATNUM (args[count+1]);
1331 timeout = XFASTINT (args[i+1]); 1337 timeout = XFASTINT (args[count+1]);
1332 i = i+2; 1338 count = count+2;
1333 } 1339 }
1334 1340
1335 /* Initialize parameter list of message. */ 1341 /* Initialize parameter list of message. */
1336 dbus_message_iter_init_append (dmessage, &iter); 1342 dbus_message_iter_init_append (dmessage, &iter);
1337 1343
1338 /* Append parameters to the message. */ 1344 /* Append parameters to the message. */
1339 for (; i < nargs; ++i) 1345 for (; count < nargs; ++count)
1340 { 1346 {
1341 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]); 1347 dtype = XD_OBJECT_TO_DBUS_TYPE (args[count]);
1342 if (XD_DBUS_TYPE_P (args[i])) 1348 if (XD_DBUS_TYPE_P (args[count]))
1343 { 1349 {
1344 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]); 1350 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1345 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]); 1351 XD_DEBUG_VALID_LISP_OBJECT_P (args[count+1]);
1346 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4, 1352 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", count - 4,
1347 SDATA (format2 ("%s", args[i], Qnil)), 1353 XD_OBJECT_TO_STRING (args[count]),
1348 SDATA (format2 ("%s", args[i+1], Qnil))); 1354 XD_OBJECT_TO_STRING (args[count+1]));
1349 ++i; 1355 ++count;
1350 } 1356 }
1351 else 1357 else
1352 { 1358 {
1353 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]); 1359 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1354 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4, 1360 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", count - 4,
1355 SDATA (format2 ("%s", args[i], Qnil))); 1361 XD_OBJECT_TO_STRING (args[count]));
1356 } 1362 }
1357 1363
1358 /* Check for valid signature. We use DBUS_TYPE_INVALID as 1364 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1359 indication that there is no parent type. */ 1365 indication that there is no parent type. */
1360 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]); 1366 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[count]);
1361 1367
1362 xd_append_arg (dtype, args[i], &iter); 1368 xd_append_arg (dtype, args[count], &iter);
1363 } 1369 }
1364 1370
1365 if (!NILP (handler)) 1371 if (!NILP (handler))
@@ -1368,11 +1374,15 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
1368 message queue. */ 1374 message queue. */
1369 if (!dbus_connection_send_with_reply (connection, dmessage, 1375 if (!dbus_connection_send_with_reply (connection, dmessage,
1370 NULL, timeout)) 1376 NULL, timeout))
1371 XD_SIGNAL1 (build_string ("Cannot send message")); 1377 {
1378 UNGCPRO;
1379 XD_SIGNAL1 (build_string ("Cannot send message"));
1380 }
1372 1381
1373 /* The result is the key in Vdbus_registered_objects_table. */ 1382 /* The result is the key in Vdbus_registered_objects_table. */
1374 serial = dbus_message_get_serial (dmessage); 1383 serial = dbus_message_get_serial (dmessage);
1375 result = list2 (bus, make_fixnum_or_float (serial)); 1384 result = list3 (QCdbus_registered_serial,
1385 bus, make_fixnum_or_float (serial));
1376 1386
1377 /* Create a hash table entry. */ 1387 /* Create a hash table entry. */
1378 Fputhash (result, handler, Vdbus_registered_objects_table); 1388 Fputhash (result, handler, Vdbus_registered_objects_table);
@@ -1382,12 +1392,15 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
1382 /* Send the message. The message is just added to the outgoing 1392 /* Send the message. The message is just added to the outgoing
1383 message queue. */ 1393 message queue. */
1384 if (!dbus_connection_send (connection, dmessage, NULL)) 1394 if (!dbus_connection_send (connection, dmessage, NULL))
1385 XD_SIGNAL1 (build_string ("Cannot send message")); 1395 {
1396 UNGCPRO;
1397 XD_SIGNAL1 (build_string ("Cannot send message"));
1398 }
1386 1399
1387 result = Qnil; 1400 result = Qnil;
1388 } 1401 }
1389 1402
1390 XD_DEBUG_MESSAGE ("Message sent"); 1403 XD_DEBUG_MESSAGE ("Message sent: %s", XD_OBJECT_TO_STRING (result));
1391 1404
1392 /* Cleanup. */ 1405 /* Cleanup. */
1393 dbus_message_unref (dmessage); 1406 dbus_message_unref (dmessage);
@@ -1396,300 +1409,6 @@ usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLE
1396 RETURN_UNGCPRO (result); 1409 RETURN_UNGCPRO (result);
1397} 1410}
1398 1411
1399DEFUN ("dbus-method-return-internal", Fdbus_method_return_internal,
1400 Sdbus_method_return_internal,
1401 3, MANY, 0,
1402 doc: /* Return for message SERIAL on the D-Bus BUS.
1403This is an internal function, it shall not be used outside dbus.el.
1404
1405usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
1406 (ptrdiff_t nargs, Lisp_Object *args)
1407{
1408 Lisp_Object bus, service;
1409 struct gcpro gcpro1, gcpro2;
1410 DBusConnection *connection;
1411 DBusMessage *dmessage;
1412 DBusMessageIter iter;
1413 dbus_uint32_t serial;
1414 unsigned int ui_serial, dtype;
1415 ptrdiff_t i;
1416 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1417
1418 /* Check parameters. */
1419 bus = args[0];
1420 service = args[2];
1421
1422 CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
1423 CHECK_STRING (service);
1424 GCPRO2 (bus, service);
1425
1426 ui_serial = serial;
1427 XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
1428
1429 /* Open a connection to the bus. */
1430 connection = xd_initialize (bus, TRUE);
1431
1432 /* Create the message. */
1433 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1434 if ((dmessage == NULL)
1435 || (!dbus_message_set_reply_serial (dmessage, serial))
1436 || (!dbus_message_set_destination (dmessage, SSDATA (service))))
1437 {
1438 UNGCPRO;
1439 XD_SIGNAL1 (build_string ("Unable to create a return message"));
1440 }
1441
1442 UNGCPRO;
1443
1444 /* Initialize parameter list of message. */
1445 dbus_message_iter_init_append (dmessage, &iter);
1446
1447 /* Append parameters to the message. */
1448 for (i = 3; i < nargs; ++i)
1449 {
1450 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1451 if (XD_DBUS_TYPE_P (args[i]))
1452 {
1453 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1454 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1455 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 2,
1456 SDATA (format2 ("%s", args[i], Qnil)),
1457 SDATA (format2 ("%s", args[i+1], Qnil)));
1458 ++i;
1459 }
1460 else
1461 {
1462 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1463 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 2,
1464 SDATA (format2 ("%s", args[i], Qnil)));
1465 }
1466
1467 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1468 indication that there is no parent type. */
1469 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1470
1471 xd_append_arg (dtype, args[i], &iter);
1472 }
1473
1474 /* Send the message. The message is just added to the outgoing
1475 message queue. */
1476 if (!dbus_connection_send (connection, dmessage, NULL))
1477 XD_SIGNAL1 (build_string ("Cannot send message"));
1478
1479 XD_DEBUG_MESSAGE ("Message sent");
1480
1481 /* Cleanup. */
1482 dbus_message_unref (dmessage);
1483
1484 /* Return. */
1485 return Qt;
1486}
1487
1488DEFUN ("dbus-method-error-internal", Fdbus_method_error_internal,
1489 Sdbus_method_error_internal,
1490 3, MANY, 0,
1491 doc: /* Return error message for message SERIAL on the D-Bus BUS.
1492This is an internal function, it shall not be used outside dbus.el.
1493
1494usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
1495 (ptrdiff_t nargs, Lisp_Object *args)
1496{
1497 Lisp_Object bus, service;
1498 struct gcpro gcpro1, gcpro2;
1499 DBusConnection *connection;
1500 DBusMessage *dmessage;
1501 DBusMessageIter iter;
1502 dbus_uint32_t serial;
1503 unsigned int ui_serial, dtype;
1504 ptrdiff_t i;
1505 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1506
1507 /* Check parameters. */
1508 bus = args[0];
1509 service = args[2];
1510
1511 CHECK_DBUS_SERIAL_GET_SERIAL (args[1], serial);
1512 CHECK_STRING (service);
1513 GCPRO2 (bus, service);
1514
1515 ui_serial = serial;
1516 XD_DEBUG_MESSAGE ("%u %s ", ui_serial, SSDATA (service));
1517
1518 /* Open a connection to the bus. */
1519 connection = xd_initialize (bus, TRUE);
1520
1521 /* Create the message. */
1522 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1523 if ((dmessage == NULL)
1524 || (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED))
1525 || (!dbus_message_set_reply_serial (dmessage, serial))
1526 || (!dbus_message_set_destination (dmessage, SSDATA (service))))
1527 {
1528 UNGCPRO;
1529 XD_SIGNAL1 (build_string ("Unable to create a error message"));
1530 }
1531
1532 UNGCPRO;
1533
1534 /* Initialize parameter list of message. */
1535 dbus_message_iter_init_append (dmessage, &iter);
1536
1537 /* Append parameters to the message. */
1538 for (i = 3; i < nargs; ++i)
1539 {
1540 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1541 if (XD_DBUS_TYPE_P (args[i]))
1542 {
1543 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1544 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1545 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 2,
1546 SDATA (format2 ("%s", args[i], Qnil)),
1547 SDATA (format2 ("%s", args[i+1], Qnil)));
1548 ++i;
1549 }
1550 else
1551 {
1552 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1553 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 2,
1554 SDATA (format2 ("%s", args[i], Qnil)));
1555 }
1556
1557 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1558 indication that there is no parent type. */
1559 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1560
1561 xd_append_arg (dtype, args[i], &iter);
1562 }
1563
1564 /* Send the message. The message is just added to the outgoing
1565 message queue. */
1566 if (!dbus_connection_send (connection, dmessage, NULL))
1567 XD_SIGNAL1 (build_string ("Cannot send message"));
1568
1569 XD_DEBUG_MESSAGE ("Message sent");
1570
1571 /* Cleanup. */
1572 dbus_message_unref (dmessage);
1573
1574 /* Return. */
1575 return Qt;
1576}
1577
1578DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
1579 doc: /* Send signal SIGNAL on the D-Bus BUS.
1580
1581BUS is either a Lisp symbol, `:system' or `:session', or a string
1582denoting the bus address.
1583
1584SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
1585D-Bus object path SERVICE is registered at. INTERFACE is an interface
1586offered by SERVICE. It must provide signal SIGNAL.
1587
1588All other arguments ARGS are passed to SIGNAL as arguments. They are
1589converted into D-Bus types via the following rules:
1590
1591 t and nil => DBUS_TYPE_BOOLEAN
1592 number => DBUS_TYPE_UINT32
1593 integer => DBUS_TYPE_INT32
1594 float => DBUS_TYPE_DOUBLE
1595 string => DBUS_TYPE_STRING
1596 list => DBUS_TYPE_ARRAY
1597
1598All arguments can be preceded by a type symbol. For details about
1599type symbols, see Info node `(dbus)Type Conversion'.
1600
1601Example:
1602
1603\(dbus-send-signal
1604 :session "org.gnu.Emacs" "/org/gnu/Emacs"
1605 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
1606
1607usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
1608 (ptrdiff_t nargs, Lisp_Object *args)
1609{
1610 Lisp_Object bus, service, path, interface, signal;
1611 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1612 DBusConnection *connection;
1613 DBusMessage *dmessage;
1614 DBusMessageIter iter;
1615 unsigned int dtype;
1616 ptrdiff_t i;
1617 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1618
1619 /* Check parameters. */
1620 bus = args[0];
1621 service = args[1];
1622 path = args[2];
1623 interface = args[3];
1624 signal = args[4];
1625
1626 CHECK_STRING (service);
1627 CHECK_STRING (path);
1628 CHECK_STRING (interface);
1629 CHECK_STRING (signal);
1630 GCPRO5 (bus, service, path, interface, signal);
1631
1632 XD_DEBUG_MESSAGE ("%s %s %s %s",
1633 SDATA (service),
1634 SDATA (path),
1635 SDATA (interface),
1636 SDATA (signal));
1637
1638 /* Open a connection to the bus. */
1639 connection = xd_initialize (bus, TRUE);
1640
1641 /* Create the message. */
1642 dmessage = dbus_message_new_signal (SSDATA (path),
1643 SSDATA (interface),
1644 SSDATA (signal));
1645 UNGCPRO;
1646 if (dmessage == NULL)
1647 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1648
1649 /* Initialize parameter list of message. */
1650 dbus_message_iter_init_append (dmessage, &iter);
1651
1652 /* Append parameters to the message. */
1653 for (i = 5; i < nargs; ++i)
1654 {
1655 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1656 if (XD_DBUS_TYPE_P (args[i]))
1657 {
1658 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1659 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1660 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", i - 4,
1661 SDATA (format2 ("%s", args[i], Qnil)),
1662 SDATA (format2 ("%s", args[i+1], Qnil)));
1663 ++i;
1664 }
1665 else
1666 {
1667 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1668 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", i - 4,
1669 SDATA (format2 ("%s", args[i], Qnil)));
1670 }
1671
1672 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1673 indication that there is no parent type. */
1674 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1675
1676 xd_append_arg (dtype, args[i], &iter);
1677 }
1678
1679 /* Send the message. The message is just added to the outgoing
1680 message queue. */
1681 if (!dbus_connection_send (connection, dmessage, NULL))
1682 XD_SIGNAL1 (build_string ("Cannot send message"));
1683
1684 XD_DEBUG_MESSAGE ("Signal sent");
1685
1686 /* Cleanup. */
1687 dbus_message_unref (dmessage);
1688
1689 /* Return. */
1690 return Qt;
1691}
1692
1693/* Read one queued incoming message of the D-Bus BUS. 1412/* Read one queued incoming message of the D-Bus BUS.
1694 BUS is either a Lisp symbol, :system or :session, or a string denoting 1413 BUS is either a Lisp symbol, :system or :session, or a string denoting
1695 the bus address. */ 1414 the bus address. */
@@ -1702,7 +1421,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1702 DBusMessage *dmessage; 1421 DBusMessage *dmessage;
1703 DBusMessageIter iter; 1422 DBusMessageIter iter;
1704 unsigned int dtype; 1423 unsigned int dtype;
1705 int mtype; 1424 unsigned int mtype;
1706 dbus_uint32_t serial; 1425 dbus_uint32_t serial;
1707 unsigned int ui_serial; 1426 unsigned int ui_serial;
1708 const char *uname, *path, *interface, *member; 1427 const char *uname, *path, *interface, *member;
@@ -1744,23 +1463,19 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1744 member = dbus_message_get_member (dmessage); 1463 member = dbus_message_get_member (dmessage);
1745 1464
1746 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s", 1465 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
1747 (mtype == DBUS_MESSAGE_TYPE_INVALID) 1466 XD_MESSAGE_TYPE_TO_STRING (mtype),
1748 ? "DBUS_MESSAGE_TYPE_INVALID"
1749 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1750 ? "DBUS_MESSAGE_TYPE_METHOD_CALL"
1751 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1752 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN"
1753 : (mtype == DBUS_MESSAGE_TYPE_ERROR)
1754 ? "DBUS_MESSAGE_TYPE_ERROR"
1755 : "DBUS_MESSAGE_TYPE_SIGNAL",
1756 ui_serial, uname, path, interface, member, 1467 ui_serial, uname, path, interface, member,
1757 SDATA (format2 ("%s", args, Qnil))); 1468 XD_OBJECT_TO_STRING (args));
1469
1470 if (mtype == DBUS_MESSAGE_TYPE_INVALID)
1471 goto cleanup;
1758 1472
1759 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN) 1473 else if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1760 || (mtype == DBUS_MESSAGE_TYPE_ERROR)) 1474 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1761 { 1475 {
1762 /* Search for a registered function of the message. */ 1476 /* Search for a registered function of the message. */
1763 key = list2 (bus, make_fixnum_or_float (serial)); 1477 key = list3 (QCdbus_registered_serial, bus,
1478 make_fixnum_or_float (serial));
1764 value = Fgethash (key, Vdbus_registered_objects_table, Qnil); 1479 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
1765 1480
1766 /* There shall be exactly one entry. Construct an event. */ 1481 /* There shall be exactly one entry. Construct an event. */
@@ -1777,7 +1492,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1777 event.arg = Fcons (value, args); 1492 event.arg = Fcons (value, args);
1778 } 1493 }
1779 1494
1780 else /* (mtype != DBUS_MESSAGE_TYPE_METHOD_RETURN) */ 1495 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
1781 { 1496 {
1782 /* Vdbus_registered_objects_table requires non-nil interface and 1497 /* Vdbus_registered_objects_table requires non-nil interface and
1783 member. */ 1498 member. */
@@ -1785,7 +1500,10 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1785 goto cleanup; 1500 goto cleanup;
1786 1501
1787 /* Search for a registered function of the message. */ 1502 /* Search for a registered function of the message. */
1788 key = list3 (bus, build_string (interface), build_string (member)); 1503 key = list4 ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1504 ? QCdbus_registered_method
1505 : QCdbus_registered_signal,
1506 bus, build_string (interface), build_string (member));
1789 value = Fgethash (key, Vdbus_registered_objects_table, Qnil); 1507 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
1790 1508
1791 /* Loop over the registered functions. Construct an event. */ 1509 /* Loop over the registered functions. Construct an event. */
@@ -1835,8 +1553,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1835 /* Store it into the input event queue. */ 1553 /* Store it into the input event queue. */
1836 kbd_buffer_store_event (&event); 1554 kbd_buffer_store_event (&event);
1837 1555
1838 XD_DEBUG_MESSAGE ("Event stored: %s", 1556 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
1839 SDATA (format2 ("%s", event.arg, Qnil)));
1840 1557
1841 /* Cleanup. */ 1558 /* Cleanup. */
1842 cleanup: 1559 cleanup:
@@ -1851,8 +1568,8 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1851static Lisp_Object 1568static Lisp_Object
1852xd_read_message (Lisp_Object bus) 1569xd_read_message (Lisp_Object bus)
1853{ 1570{
1854 /* Open a connection to the bus. */ 1571 /* Retrieve bus address. */
1855 DBusConnection *connection = xd_initialize (bus, TRUE); 1572 DBusConnection *connection = xd_get_connection_address (bus);
1856 1573
1857 /* Non blocking read of the next available message. */ 1574 /* Non blocking read of the next available message. */
1858 dbus_connection_read_write (connection, 0); 1575 dbus_connection_read_write (connection, 0);
@@ -1869,14 +1586,16 @@ xd_read_queued_messages (int fd, void *data, int for_read)
1869{ 1586{
1870 Lisp_Object busp = Vdbus_registered_buses; 1587 Lisp_Object busp = Vdbus_registered_buses;
1871 Lisp_Object bus = Qnil; 1588 Lisp_Object bus = Qnil;
1589 Lisp_Object key;
1872 1590
1873 /* Find bus related to fd. */ 1591 /* Find bus related to fd. */
1874 if (data != NULL) 1592 if (data != NULL)
1875 while (!NILP (busp)) 1593 while (!NILP (busp))
1876 { 1594 {
1877 if ((SYMBOLP (CAR_SAFE (busp)) && XSYMBOL (CAR_SAFE (busp)) == data) 1595 key = CAR_SAFE (CAR_SAFE (busp));
1878 || (STRINGP (CAR_SAFE (busp)) && XSTRING (CAR_SAFE (busp)) == data)) 1596 if ((SYMBOLP (key) && XSYMBOL (key) == data)
1879 bus = CAR_SAFE (busp); 1597 || (STRINGP (key) && XSTRING (key) == data))
1598 bus = key;
1880 busp = CDR_SAFE (busp); 1599 busp = CDR_SAFE (busp);
1881 } 1600 }
1882 1601
@@ -1889,327 +1608,6 @@ xd_read_queued_messages (int fd, void *data, int for_read)
1889 xd_in_read_queued_messages = 0; 1608 xd_in_read_queued_messages = 0;
1890} 1609}
1891 1610
1892DEFUN ("dbus-register-service", Fdbus_register_service, Sdbus_register_service,
1893 2, MANY, 0,
1894 doc: /* Register known name SERVICE on the D-Bus BUS.
1895
1896BUS is either a Lisp symbol, `:system' or `:session', or a string
1897denoting the bus address.
1898
1899SERVICE is the D-Bus service name that should be registered. It must
1900be a known name.
1901
1902FLAGS are keywords, which control how the service name is registered.
1903The following keywords are recognized:
1904
1905`:allow-replacement': Allow another service to become the primary
1906owner if requested.
1907
1908`:replace-existing': Request to replace the current primary owner.
1909
1910`:do-not-queue': If we can not become the primary owner do not place
1911us in the queue.
1912
1913The function returns a keyword, indicating the result of the
1914operation. One of the following keywords is returned:
1915
1916`:primary-owner': Service has become the primary owner of the
1917requested name.
1918
1919`:in-queue': Service could not become the primary owner and has been
1920placed in the queue.
1921
1922`:exists': Service is already in the queue.
1923
1924`:already-owner': Service is already the primary owner.
1925
1926Example:
1927
1928\(dbus-register-service :session dbus-service-emacs)
1929
1930 => :primary-owner.
1931
1932\(dbus-register-service
1933 :session "org.freedesktop.TextEditor"
1934 dbus-service-allow-replacement dbus-service-replace-existing)
1935
1936 => :already-owner.
1937
1938usage: (dbus-register-service BUS SERVICE &rest FLAGS) */)
1939 (ptrdiff_t nargs, Lisp_Object *args)
1940{
1941 Lisp_Object bus, service;
1942 DBusConnection *connection;
1943 ptrdiff_t i;
1944 unsigned int value;
1945 unsigned int flags = 0;
1946 int result;
1947 DBusError derror;
1948
1949 bus = args[0];
1950 service = args[1];
1951
1952 /* Check parameters. */
1953 CHECK_STRING (service);
1954
1955 /* Process flags. */
1956 for (i = 2; i < nargs; ++i) {
1957 value = ((EQ (args[i], QCdbus_request_name_replace_existing))
1958 ? DBUS_NAME_FLAG_REPLACE_EXISTING
1959 : (EQ (args[i], QCdbus_request_name_allow_replacement))
1960 ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT
1961 : (EQ (args[i], QCdbus_request_name_do_not_queue))
1962 ? DBUS_NAME_FLAG_DO_NOT_QUEUE
1963 : -1);
1964 if (value == -1)
1965 XD_SIGNAL2 (build_string ("Unrecognized name request flag"), args[i]);
1966 flags |= value;
1967 }
1968
1969 /* Open a connection to the bus. */
1970 connection = xd_initialize (bus, TRUE);
1971
1972 /* Request the known name from the bus. */
1973 dbus_error_init (&derror);
1974 result = dbus_bus_request_name (connection, SSDATA (service), flags,
1975 &derror);
1976 if (dbus_error_is_set (&derror))
1977 XD_ERROR (derror);
1978
1979 /* Cleanup. */
1980 dbus_error_free (&derror);
1981
1982 /* Return object. */
1983 switch (result)
1984 {
1985 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1986 return QCdbus_request_name_reply_primary_owner;
1987 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1988 return QCdbus_request_name_reply_in_queue;
1989 case DBUS_REQUEST_NAME_REPLY_EXISTS:
1990 return QCdbus_request_name_reply_exists;
1991 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1992 return QCdbus_request_name_reply_already_owner;
1993 default:
1994 /* This should not happen. */
1995 XD_SIGNAL2 (build_string ("Could not register service"), service);
1996 }
1997}
1998
1999DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
2000 6, MANY, 0,
2001 doc: /* Register for signal SIGNAL on the D-Bus BUS.
2002
2003BUS is either a Lisp symbol, `:system' or `:session', or a string
2004denoting the bus address.
2005
2006SERVICE is the D-Bus service name used by the sending D-Bus object.
2007It can be either a known name or the unique name of the D-Bus object
2008sending the signal. When SERVICE is nil, related signals from all
2009D-Bus objects shall be accepted.
2010
2011PATH is the D-Bus object path SERVICE is registered. It can also be
2012nil if the path name of incoming signals shall not be checked.
2013
2014INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
2015HANDLER is a Lisp function to be called when the signal is received.
2016It must accept as arguments the values SIGNAL is sending.
2017
2018All other arguments ARGS, if specified, must be strings. They stand
2019for the respective arguments of the signal in their order, and are
2020used for filtering as well. A nil argument might be used to preserve
2021the order.
2022
2023INTERFACE, SIGNAL and HANDLER must not be nil. Example:
2024
2025\(defun my-signal-handler (device)
2026 (message "Device %s added" device))
2027
2028\(dbus-register-signal
2029 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
2030 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
2031
2032 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
2033 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
2034
2035`dbus-register-signal' returns an object, which can be used in
2036`dbus-unregister-object' for removing the registration.
2037
2038usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
2039 (ptrdiff_t nargs, Lisp_Object *args)
2040{
2041 Lisp_Object bus, service, path, interface, signal, handler;
2042 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
2043 Lisp_Object uname, key, key1, value;
2044 DBusConnection *connection;
2045 ptrdiff_t i;
2046 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
2047 int rulelen;
2048 DBusError derror;
2049
2050 /* Check parameters. */
2051 bus = args[0];
2052 service = args[1];
2053 path = args[2];
2054 interface = args[3];
2055 signal = args[4];
2056 handler = args[5];
2057
2058 if (!NILP (service)) CHECK_STRING (service);
2059 if (!NILP (path)) CHECK_STRING (path);
2060 CHECK_STRING (interface);
2061 CHECK_STRING (signal);
2062 if (!FUNCTIONP (handler))
2063 wrong_type_argument (Qinvalid_function, handler);
2064 GCPRO6 (bus, service, path, interface, signal, handler);
2065
2066 /* Retrieve unique name of service. If service is a known name, we
2067 will register for the corresponding unique name, if any. Signals
2068 are sent always with the unique name as sender. Note: the unique
2069 name of "org.freedesktop.DBus" is that string itself. */
2070 if ((STRINGP (service))
2071 && (SBYTES (service) > 0)
2072 && (strcmp (SSDATA (service), DBUS_SERVICE_DBUS) != 0)
2073 && (strncmp (SSDATA (service), ":", 1) != 0))
2074 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
2075 else
2076 uname = service;
2077
2078 /* Create a matching rule if the unique name exists (when no
2079 wildcard). */
2080 if (NILP (uname) || (SBYTES (uname) > 0))
2081 {
2082 /* Open a connection to the bus. */
2083 connection = xd_initialize (bus, TRUE);
2084
2085 /* Create a rule to receive related signals. */
2086 rulelen = snprintf (rule, sizeof rule,
2087 "type='signal',interface='%s',member='%s'",
2088 SDATA (interface),
2089 SDATA (signal));
2090 if (! (0 <= rulelen && rulelen < sizeof rule))
2091 string_overflow ();
2092
2093 /* Add unique name and path to the rule if they are non-nil. */
2094 if (!NILP (uname))
2095 {
2096 int len = snprintf (rule + rulelen, sizeof rule - rulelen,
2097 ",sender='%s'", SDATA (uname));
2098 if (! (0 <= len && len < sizeof rule - rulelen))
2099 string_overflow ();
2100 rulelen += len;
2101 }
2102
2103 if (!NILP (path))
2104 {
2105 int len = snprintf (rule + rulelen, sizeof rule - rulelen,
2106 ",path='%s'", SDATA (path));
2107 if (! (0 <= len && len < sizeof rule - rulelen))
2108 string_overflow ();
2109 rulelen += len;
2110 }
2111
2112 /* Add arguments to the rule if they are non-nil. */
2113 for (i = 6; i < nargs; ++i)
2114 if (!NILP (args[i]))
2115 {
2116 int len;
2117 CHECK_STRING (args[i]);
2118 len = snprintf (rule + rulelen, sizeof rule - rulelen,
2119 ",arg%"pD"d='%s'", i - 6, SDATA (args[i]));
2120 if (! (0 <= len && len < sizeof rule - rulelen))
2121 string_overflow ();
2122 rulelen += len;
2123 }
2124
2125 /* Add the rule to the bus. */
2126 dbus_error_init (&derror);
2127 dbus_bus_add_match (connection, rule, &derror);
2128 if (dbus_error_is_set (&derror))
2129 {
2130 UNGCPRO;
2131 XD_ERROR (derror);
2132 }
2133
2134 /* Cleanup. */
2135 dbus_error_free (&derror);
2136
2137 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
2138 }
2139
2140 /* Create a hash table entry. */
2141 key = list3 (bus, interface, signal);
2142 key1 = list5 (uname, service, path, handler, build_string (rule));
2143 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
2144
2145 if (NILP (Fmember (key1, value)))
2146 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
2147
2148 /* Return object. */
2149 RETURN_UNGCPRO (list2 (key, list3 (service, path, handler)));
2150}
2151
2152DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
2153 6, 7, 0,
2154 doc: /* Register for method METHOD on the D-Bus BUS.
2155
2156BUS is either a Lisp symbol, `:system' or `:session', or a string
2157denoting the bus address.
2158
2159SERVICE is the D-Bus service name of the D-Bus object METHOD is
2160registered for. It must be a known name (See discussion of
2161DONT-REGISTER-SERVICE below).
2162
2163PATH is the D-Bus object path SERVICE is registered (See discussion of
2164DONT-REGISTER-SERVICE below). INTERFACE is the interface offered by
2165SERVICE. It must provide METHOD.
2166
2167HANDLER is a Lisp function to be called when a method call is
2168received. It must accept the input arguments of METHOD. The return
2169value of HANDLER is used for composing the returning D-Bus message.
2170In case HANDLER shall return a reply message with an empty argument
2171list, HANDLER must return the symbol `:ignore'.
2172
2173When DONT-REGISTER-SERVICE is non-nil, the known name SERVICE is not
2174registered. This means that other D-Bus clients have no way of
2175noticing the newly registered method. When interfaces are constructed
2176incrementally by adding single methods or properties at a time,
2177DONT-REGISTER-SERVICE can be used to prevent other clients from
2178discovering the still incomplete interface.*/)
2179 (Lisp_Object bus, Lisp_Object service, Lisp_Object path,
2180 Lisp_Object interface, Lisp_Object method, Lisp_Object handler,
2181 Lisp_Object dont_register_service)
2182{
2183 Lisp_Object key, key1, value;
2184 Lisp_Object args[2] = { bus, service };
2185
2186 /* Check parameters. */
2187 CHECK_STRING (service);
2188 CHECK_STRING (path);
2189 CHECK_STRING (interface);
2190 CHECK_STRING (method);
2191 if (!FUNCTIONP (handler))
2192 wrong_type_argument (Qinvalid_function, handler);
2193 /* TODO: We must check for a valid service name, otherwise there is
2194 a segmentation fault. */
2195
2196 /* Request the name. */
2197 if (NILP (dont_register_service))
2198 Fdbus_register_service (2, args);
2199
2200 /* Create a hash table entry. We use nil for the unique name,
2201 because the method might be called from anybody. */
2202 key = list3 (bus, interface, method);
2203 key1 = list4 (Qnil, service, path, handler);
2204 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
2205
2206 if (NILP (Fmember (key1, value)))
2207 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
2208
2209 /* Return object. */
2210 return list2 (key, list3 (service, path, handler));
2211}
2212
2213 1611
2214void 1612void
2215syms_of_dbusbind (void) 1613syms_of_dbusbind (void)
@@ -2218,35 +1616,11 @@ syms_of_dbusbind (void)
2218 DEFSYM (Qdbus_init_bus, "dbus-init-bus"); 1616 DEFSYM (Qdbus_init_bus, "dbus-init-bus");
2219 defsubr (&Sdbus_init_bus); 1617 defsubr (&Sdbus_init_bus);
2220 1618
2221 DEFSYM (Qdbus_close_bus, "dbus-close-bus");
2222 defsubr (&Sdbus_close_bus);
2223
2224 DEFSYM (Qdbus_get_unique_name, "dbus-get-unique-name"); 1619 DEFSYM (Qdbus_get_unique_name, "dbus-get-unique-name");
2225 defsubr (&Sdbus_get_unique_name); 1620 defsubr (&Sdbus_get_unique_name);
2226 1621
2227 DEFSYM (Qdbus_call_method, "dbus-call-method"); 1622 DEFSYM (Qdbus_message_internal, "dbus-message-internal");
2228 defsubr (&Sdbus_call_method); 1623 defsubr (&Sdbus_message_internal);
2229
2230 DEFSYM (Qdbus_call_method_asynchronously, "dbus-call-method-asynchronously");
2231 defsubr (&Sdbus_call_method_asynchronously);
2232
2233 DEFSYM (Qdbus_method_return_internal, "dbus-method-return-internal");
2234 defsubr (&Sdbus_method_return_internal);
2235
2236 DEFSYM (Qdbus_method_error_internal, "dbus-method-error-internal");
2237 defsubr (&Sdbus_method_error_internal);
2238
2239 DEFSYM (Qdbus_send_signal, "dbus-send-signal");
2240 defsubr (&Sdbus_send_signal);
2241
2242 DEFSYM (Qdbus_register_service, "dbus-register-service");
2243 defsubr (&Sdbus_register_service);
2244
2245 DEFSYM (Qdbus_register_signal, "dbus-register-signal");
2246 defsubr (&Sdbus_register_signal);
2247
2248 DEFSYM (Qdbus_register_method, "dbus-register-method");
2249 defsubr (&Sdbus_register_method);
2250 1624
2251 DEFSYM (Qdbus_error, "dbus-error"); 1625 DEFSYM (Qdbus_error, "dbus-error");
2252 Fput (Qdbus_error, Qerror_conditions, 1626 Fput (Qdbus_error, Qerror_conditions,
@@ -2256,13 +1630,6 @@ syms_of_dbusbind (void)
2256 1630
2257 DEFSYM (QCdbus_system_bus, ":system"); 1631 DEFSYM (QCdbus_system_bus, ":system");
2258 DEFSYM (QCdbus_session_bus, ":session"); 1632 DEFSYM (QCdbus_session_bus, ":session");
2259 DEFSYM (QCdbus_request_name_allow_replacement, ":allow-replacement");
2260 DEFSYM (QCdbus_request_name_replace_existing, ":replace-existing");
2261 DEFSYM (QCdbus_request_name_do_not_queue, ":do-not-queue");
2262 DEFSYM (QCdbus_request_name_reply_primary_owner, ":primary-owner");
2263 DEFSYM (QCdbus_request_name_reply_exists, ":exists");
2264 DEFSYM (QCdbus_request_name_reply_in_queue, ":in-queue");
2265 DEFSYM (QCdbus_request_name_reply_already_owner, ":already-owner");
2266 DEFSYM (QCdbus_timeout, ":timeout"); 1633 DEFSYM (QCdbus_timeout, ":timeout");
2267 DEFSYM (QCdbus_type_byte, ":byte"); 1634 DEFSYM (QCdbus_type_byte, ":byte");
2268 DEFSYM (QCdbus_type_boolean, ":boolean"); 1635 DEFSYM (QCdbus_type_boolean, ":boolean");
@@ -2276,19 +1643,73 @@ syms_of_dbusbind (void)
2276 DEFSYM (QCdbus_type_string, ":string"); 1643 DEFSYM (QCdbus_type_string, ":string");
2277 DEFSYM (QCdbus_type_object_path, ":object-path"); 1644 DEFSYM (QCdbus_type_object_path, ":object-path");
2278 DEFSYM (QCdbus_type_signature, ":signature"); 1645 DEFSYM (QCdbus_type_signature, ":signature");
2279
2280#ifdef DBUS_TYPE_UNIX_FD 1646#ifdef DBUS_TYPE_UNIX_FD
2281 DEFSYM (QCdbus_type_unix_fd, ":unix-fd"); 1647 DEFSYM (QCdbus_type_unix_fd, ":unix-fd");
2282#endif 1648#endif
2283
2284 DEFSYM (QCdbus_type_array, ":array"); 1649 DEFSYM (QCdbus_type_array, ":array");
2285 DEFSYM (QCdbus_type_variant, ":variant"); 1650 DEFSYM (QCdbus_type_variant, ":variant");
2286 DEFSYM (QCdbus_type_struct, ":struct"); 1651 DEFSYM (QCdbus_type_struct, ":struct");
2287 DEFSYM (QCdbus_type_dict_entry, ":dict-entry"); 1652 DEFSYM (QCdbus_type_dict_entry, ":dict-entry");
1653 DEFSYM (QCdbus_registered_serial, ":serial");
1654 DEFSYM (QCdbus_registered_method, ":method");
1655 DEFSYM (QCdbus_registered_signal, ":signal");
1656
1657 DEFVAR_LISP ("dbus-compiled-version",
1658 Vdbus_compiled_version,
1659 doc: /* The version of D-Bus Emacs is compiled against. */);
1660#ifdef DBUS_VERSION_STRING
1661 Vdbus_compiled_version = make_pure_c_string (DBUS_VERSION_STRING);
1662#else
1663 Vdbus_compiled_version = Qnil;
1664#endif
1665
1666 DEFVAR_LISP ("dbus-runtime-version",
1667 Vdbus_runtime_version,
1668 doc: /* The version of D-Bus Emacs runs with. */);
1669 {
1670#ifdef DBUS_VERSION
1671 int major, minor, micro;
1672 char s[1024];
1673 dbus_get_version (&major, &minor, &micro);
1674 snprintf (s, sizeof s, "%d.%d.%d", major, minor, micro);
1675 Vdbus_runtime_version = make_string (s, strlen (s));
1676#else
1677 Vdbus_runtime_version = Qnil;
1678#endif
1679 }
1680
1681 DEFVAR_LISP ("dbus-message-type-invalid",
1682 Vdbus_message_type_invalid,
1683 doc: /* This value is never a valid message type. */);
1684 Vdbus_message_type_invalid = make_number (DBUS_MESSAGE_TYPE_INVALID);
1685
1686 DEFVAR_LISP ("dbus-message-type-method-call",
1687 Vdbus_message_type_method_call,
1688 doc: /* Message type of a method call message. */);
1689 Vdbus_message_type_method_call = make_number (DBUS_MESSAGE_TYPE_METHOD_CALL);
1690
1691 DEFVAR_LISP ("dbus-message-type-method-return",
1692 Vdbus_message_type_method_return,
1693 doc: /* Message type of a method return message. */);
1694 Vdbus_message_type_method_return
1695 = make_number (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1696
1697 DEFVAR_LISP ("dbus-message-type-error",
1698 Vdbus_message_type_error,
1699 doc: /* Message type of an error reply message. */);
1700 Vdbus_message_type_error = make_number (DBUS_MESSAGE_TYPE_ERROR);
1701
1702 DEFVAR_LISP ("dbus-message-type-signal",
1703 Vdbus_message_type_signal,
1704 doc: /* Message type of a signal message. */);
1705 Vdbus_message_type_signal = make_number (DBUS_MESSAGE_TYPE_SIGNAL);
2288 1706
2289 DEFVAR_LISP ("dbus-registered-buses", 1707 DEFVAR_LISP ("dbus-registered-buses",
2290 Vdbus_registered_buses, 1708 Vdbus_registered_buses,
2291 doc: /* List of D-Bus buses we are polling for messages. */); 1709 doc: /* Alist of D-Bus buses we are polling for messages.
1710
1711The key is the symbol or string of the bus, and the value is the
1712connection address. */);
2292 Vdbus_registered_buses = Qnil; 1713 Vdbus_registered_buses = Qnil;
2293 1714
2294 DEFVAR_LISP ("dbus-registered-objects-table", 1715 DEFVAR_LISP ("dbus-registered-objects-table",
@@ -2299,27 +1720,28 @@ There are two different uses of the hash table: for accessing
2299registered interfaces properties, targeted by signals or method calls, 1720registered interfaces properties, targeted by signals or method calls,
2300and for calling handlers in case of non-blocking method call returns. 1721and for calling handlers in case of non-blocking method call returns.
2301 1722
2302In the first case, the key in the hash table is the list (BUS 1723In the first case, the key in the hash table is the list (TYPE BUS
2303INTERFACE MEMBER). BUS is either a Lisp symbol, `:system' or 1724INTERFACE MEMBER). TYPE is one of the Lisp symbols `:method',
1725`:signal' or `:property'. BUS is either a Lisp symbol, `:system' or
2304`:session', or a string denoting the bus address. INTERFACE is a 1726`:session', or a string denoting the bus address. INTERFACE is a
2305string which denotes a D-Bus interface, and MEMBER, also a string, is 1727string which denotes a D-Bus interface, and MEMBER, also a string, is
2306either a method, a signal or a property INTERFACE is offering. All 1728either a method, a signal or a property INTERFACE is offering. All
2307arguments but BUS must not be nil. 1729arguments but BUS must not be nil.
2308 1730
2309The value in the hash table is a list of quadruple lists 1731The value in the hash table is a list of quadruple lists \((UNAME
2310\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...). 1732SERVICE PATH OBJECT [RULE]) ...). SERVICE is the service name as
2311SERVICE is the service name as registered, UNAME is the corresponding 1733registered, UNAME is the corresponding unique name. In case of
2312unique name. In case of registered methods and properties, UNAME is 1734registered methods and properties, UNAME is nil. PATH is the object
2313nil. PATH is the object path of the sending object. All of them can 1735path of the sending object. All of them can be nil, which means a
2314be nil, which means a wildcard then. OBJECT is either the handler to 1736wildcard then. OBJECT is either the handler to be called when a D-Bus
2315be called when a D-Bus message, which matches the key criteria, 1737message, which matches the key criteria, arrives (TYPE `:method' and
2316arrives (methods and signals), or a cons cell containing the value of 1738`:signal'), or a cons cell containing the value of the property (TYPE
2317the property. 1739`:property').
2318 1740
2319For signals, there is also a fifth element RULE, which keeps the match 1741For entries of type `:signal', there is also a fifth element RULE,
2320string the signal is registered with. 1742which keeps the match string the signal is registered with.
2321 1743
2322In the second case, the key in the hash table is the list (BUS 1744In the second case, the key in the hash table is the list (:serial BUS
2323SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a 1745SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
2324string denoting the bus address. SERIAL is the serial number of the 1746string denoting the bus address. SERIAL is the serial number of the
2325non-blocking method call, a reply is expected. Both arguments must 1747non-blocking method call, a reply is expected. Both arguments must