1 /* Elisp bindings for D-Bus.
2 Copyright (C) 2007 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
26 #include <dbus/dbus.h>
29 #include "termhooks.h"
34 Lisp_Object Qdbus_get_unique_name
;
35 Lisp_Object Qdbus_call_method
;
36 Lisp_Object Qdbus_send_signal
;
37 Lisp_Object Qdbus_register_signal
;
38 Lisp_Object Qdbus_unregister_signal
;
40 /* D-Bus error symbol. */
41 Lisp_Object Qdbus_error
;
43 /* Lisp symbols of the system and session buses. */
44 Lisp_Object QCdbus_system_bus
, QCdbus_session_bus
;
46 /* Lisp symbols of D-Bus types. */
47 Lisp_Object QCdbus_type_byte
, QCdbus_type_boolean
;
48 Lisp_Object QCdbus_type_int16
, QCdbus_type_uint16
;
49 Lisp_Object QCdbus_type_int32
, QCdbus_type_uint32
;
50 Lisp_Object QCdbus_type_int64
, QCdbus_type_uint64
;
51 Lisp_Object QCdbus_type_double
, QCdbus_type_string
;
52 Lisp_Object QCdbus_type_object_path
, QCdbus_type_signature
;
53 Lisp_Object QCdbus_type_array
, QCdbus_type_variant
;
54 Lisp_Object QCdbus_type_struct
, QCdbus_type_dict_entry
;
56 /* Hash table which keeps function definitions. */
57 Lisp_Object Vdbus_registered_functions_table
;
59 /* Whether to debug D-Bus. */
60 Lisp_Object Vdbus_debug
;
63 /* We use "xd_" and "XD_" as prefix for all internal symbols, because
64 we don't want to poison other namespaces with "dbus_". */
66 /* Raise a Lisp error from a D-Bus ERROR. */
67 #define XD_ERROR(error) \
70 strcpy (s, error.message); \
71 dbus_error_free (&error); \
72 /* Remove the trailing newline. */ \
73 if (strchr (s, '\n') != NULL) \
74 s[strlen (s) - 1] = '\0'; \
75 xsignal1 (Qdbus_error, build_string (s)); \
78 /* Macros for debugging. In order to enable them, build with
79 "make MYCPPFLAGS='-DDBUS_DEBUG'". */
81 #define XD_DEBUG_MESSAGE(...) \
84 sprintf (s, __VA_ARGS__); \
85 printf ("%s: %s\n", __func__, s); \
86 message ("%s: %s", __func__, s); \
88 #define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
89 if (!valid_lisp_object_p (object)) \
91 XD_DEBUG_MESSAGE ("%s Assertion failure", __LINE__); \
92 xsignal1 (Qdbus_error, build_string ("Assertion failure")); \
95 #else /* !DBUS_DEBUG */
96 #define XD_DEBUG_MESSAGE(...) \
97 if (!NILP (Vdbus_debug)) \
100 sprintf (s, __VA_ARGS__); \
101 message ("%s: %s", __func__, s); \
103 #define XD_DEBUG_VALID_LISP_OBJECT_P(object)
106 /* Determine the DBusType of a given Lisp symbol. OBJECT must be one
107 of the predefined D-Bus type symbols. */
108 #define XD_LISP_SYMBOL_TO_DBUS_TYPE(object) \
109 (EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE \
110 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN \
111 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16 \
112 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16 \
113 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32 \
114 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32 \
115 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64 \
116 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64 \
117 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE \
118 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING \
119 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH \
120 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE \
121 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY \
122 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT \
123 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT \
124 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY \
127 /* Determine the DBusType of a given Lisp OBJECT. It is used to
128 convert Lisp objects, being arguments of `dbus-call-method' or
129 `dbus-send-signal', into corresponding C values appended as
130 arguments to a D-Bus message. */
131 #define XD_LISP_OBJECT_TO_DBUS_TYPE(object) \
132 (EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
133 : (SYMBOLP (object)) ? XD_LISP_SYMBOL_TO_DBUS_TYPE (object) \
134 : (CONSP (object)) ? ((SYMBOLP (XCAR (object)) \
135 && !EQ (XCAR (object), Qt) \
136 && !EQ (XCAR (object), Qnil)) \
137 ? XD_LISP_SYMBOL_TO_DBUS_TYPE (XCAR (object)) \
139 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
140 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
141 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
142 : (STRINGP (object)) ? DBUS_TYPE_STRING \
145 /* Append C value, extracted from Lisp OBJECT, to iteration ITER.
146 DTYPE must be a valid DBusType. It is used to convert Lisp
147 objects, being arguments of `dbus-call-method' or
148 `dbus-send-signal', into corresponding C values appended as
149 arguments to a D-Bus message. */
151 xd_append_arg (dtype
, object
, iter
)
153 DBusMessageIter
*iter
;
158 /* Check type of object. If this has been detected implicitely, it
159 is OK already, but there might be cases the type symbol and the
160 corresponding object do'nt match. */
164 case DBUS_TYPE_UINT16
:
165 case DBUS_TYPE_UINT32
:
166 case DBUS_TYPE_UINT64
:
167 CHECK_NATNUM (object
);
169 case DBUS_TYPE_BOOLEAN
:
170 if (!EQ (object
, Qt
) && !EQ (object
, Qnil
))
171 wrong_type_argument (intern ("booleanp"), object
);
173 case DBUS_TYPE_INT16
:
174 case DBUS_TYPE_INT32
:
175 case DBUS_TYPE_INT64
:
176 CHECK_NUMBER (object
);
178 case DBUS_TYPE_DOUBLE
:
179 CHECK_FLOAT (object
);
181 case DBUS_TYPE_STRING
:
182 case DBUS_TYPE_OBJECT_PATH
:
183 case DBUS_TYPE_SIGNATURE
:
184 CHECK_STRING (object
);
186 case DBUS_TYPE_ARRAY
:
188 /* ToDo: Check that all list elements have the same type. */
190 case DBUS_TYPE_VARIANT
:
192 /* ToDo: Check that there is exactly one element of basic type. */
194 case DBUS_TYPE_STRUCT
:
197 case DBUS_TYPE_DICT_ENTRY
:
198 /* ToDo: Check that there are exactly two elements, and the
199 first one is of basic type. */
203 xsignal1 (Qdbus_error
, build_string ("Unknown D-Bus type"));
208 /* Compound types. */
210 DBusMessageIter subiter
;
213 if (SYMBOLP (XCAR (object
))
214 && (strncmp (SDATA (XSYMBOL (XCAR (object
))->xname
), ":", 1) == 0))
215 object
= XCDR (object
);
217 /* Open new subiteration. */
220 case DBUS_TYPE_ARRAY
:
221 case DBUS_TYPE_VARIANT
:
222 subtype
= (char) XD_LISP_OBJECT_TO_DBUS_TYPE (XCAR (object
));
223 dbus_message_iter_open_container (iter
, dtype
, &subtype
, &subiter
);
225 case DBUS_TYPE_STRUCT
:
226 case DBUS_TYPE_DICT_ENTRY
:
227 dbus_message_iter_open_container (iter
, dtype
, NULL
, &subiter
);
230 /* Loop over list elements. */
231 while (!NILP (object
))
233 dtype
= XD_LISP_OBJECT_TO_DBUS_TYPE (XCAR (object
));
234 if (dtype
== DBUS_TYPE_INVALID
)
235 xsignal2 (Qdbus_error
,
236 build_string ("Not a valid argument"), XCAR (object
));
238 if (SYMBOLP (XCAR (object
))
239 && (strncmp (SDATA (XSYMBOL (XCAR (object
))->xname
), ":", 1)
241 object
= XCDR (object
);
243 xd_append_arg (dtype
, XCAR (object
), &subiter
);
245 object
= XCDR (object
);
248 dbus_message_iter_close_container (iter
, &subiter
);
258 XD_DEBUG_MESSAGE ("%d %u", dtype
, XUINT (object
));
259 value
= (unsigned char *) XUINT (object
);
261 case DBUS_TYPE_BOOLEAN
:
262 XD_DEBUG_MESSAGE ("%d %s", dtype
, (NILP (object
)) ? "false" : "true");
263 value
= (NILP (object
))
264 ? (unsigned char *) FALSE
: (unsigned char *) TRUE
;
266 case DBUS_TYPE_INT16
:
267 XD_DEBUG_MESSAGE ("%d %d", dtype
, XINT (object
));
268 value
= (char *) (dbus_int16_t
*) XINT (object
);
270 case DBUS_TYPE_UINT16
:
271 XD_DEBUG_MESSAGE ("%d %u", dtype
, XUINT (object
));
272 value
= (char *) (dbus_uint16_t
*) XUINT (object
);
274 case DBUS_TYPE_INT32
:
275 XD_DEBUG_MESSAGE ("%d %d", dtype
, XINT (object
));
276 value
= (char *) (dbus_int32_t
*) XINT (object
);
278 case DBUS_TYPE_UINT32
:
279 XD_DEBUG_MESSAGE ("%d %u", dtype
, XUINT (object
));
280 value
= (char *) (dbus_uint32_t
*) XUINT (object
);
282 case DBUS_TYPE_INT64
:
283 XD_DEBUG_MESSAGE ("%d %d", dtype
, XINT (object
));
284 value
= (char *) (dbus_int64_t
*) XINT (object
);
286 case DBUS_TYPE_UINT64
:
287 XD_DEBUG_MESSAGE ("%d %u", dtype
, XUINT (object
));
288 value
= (char *) (dbus_int64_t
*) XUINT (object
);
290 case DBUS_TYPE_DOUBLE
:
291 XD_DEBUG_MESSAGE ("%d %f", dtype
, XFLOAT (object
));
292 value
= (char *) (float *) XFLOAT (object
);
294 case DBUS_TYPE_STRING
:
295 case DBUS_TYPE_OBJECT_PATH
:
296 case DBUS_TYPE_SIGNATURE
:
297 XD_DEBUG_MESSAGE ("%d %s", dtype
, SDATA (object
));
298 value
= SDATA (object
);
301 if (!dbus_message_iter_append_basic (iter
, dtype
, &value
))
302 xsignal2 (Qdbus_error
,
303 build_string ("Unable to append argument"), object
);
307 /* Retrieve C value from a DBusMessageIter structure ITER, and return
308 a converted Lisp object. The type DTYPE of the argument of the
309 D-Bus message must be a valid DBusType. Compound D-Bus types are
310 partly supported; they result always in a Lisp list. */
312 xd_retrieve_arg (dtype
, iter
)
314 DBusMessageIter
*iter
;
319 case DBUS_TYPE_BOOLEAN
:
322 dbus_message_iter_get_basic (iter
, &val
);
323 XD_DEBUG_MESSAGE ("%d %s", dtype
, (val
== FALSE
) ? "false" : "true");
324 return (val
== FALSE
) ? Qnil
: Qt
;
326 case DBUS_TYPE_INT32
:
327 case DBUS_TYPE_UINT32
:
330 dbus_message_iter_get_basic (iter
, &val
);
331 XD_DEBUG_MESSAGE ("%d %d", dtype
, val
);
332 return make_number (val
);
334 case DBUS_TYPE_STRING
:
335 case DBUS_TYPE_OBJECT_PATH
:
338 dbus_message_iter_get_basic (iter
, &val
);
339 XD_DEBUG_MESSAGE ("%d %s", dtype
, val
);
340 return build_string (val
);
342 case DBUS_TYPE_ARRAY
:
343 case DBUS_TYPE_VARIANT
:
344 case DBUS_TYPE_STRUCT
:
345 case DBUS_TYPE_DICT_ENTRY
:
351 DBusMessageIter subiter
;
353 dbus_message_iter_recurse (iter
, &subiter
);
354 while ((subtype
= dbus_message_iter_get_arg_type (&subiter
))
355 != DBUS_TYPE_INVALID
)
357 result
= Fcons (xd_retrieve_arg (subtype
, &subiter
), result
);
358 dbus_message_iter_next (&subiter
);
360 RETURN_UNGCPRO (Fnreverse (result
));
363 XD_DEBUG_MESSAGE ("DBusType %d not supported", dtype
);
369 /* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
370 or :session. It tells which D-Bus to be initialized. */
375 DBusConnection
*connection
;
378 /* Parameter check. */
380 if (!((EQ (bus
, QCdbus_system_bus
)) || (EQ (bus
, QCdbus_session_bus
))))
381 xsignal2 (Qdbus_error
, build_string ("Wrong bus name"), bus
);
383 /* Open a connection to the bus. */
384 dbus_error_init (&derror
);
386 if (EQ (bus
, QCdbus_system_bus
))
387 connection
= dbus_bus_get (DBUS_BUS_SYSTEM
, &derror
);
389 connection
= dbus_bus_get (DBUS_BUS_SESSION
, &derror
);
391 if (dbus_error_is_set (&derror
))
394 if (connection
== NULL
)
395 xsignal2 (Qdbus_error
, build_string ("No connection"), bus
);
397 /* Return the result. */
401 DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name
, Sdbus_get_unique_name
,
403 doc
: /* Return the unique name of Emacs registered at D-Bus BUS as string. */)
407 DBusConnection
*connection
;
408 char name
[DBUS_MAXIMUM_NAME_LENGTH
];
410 /* Check parameters. */
413 /* Open a connection to the bus. */
414 connection
= xd_initialize (bus
);
416 /* Request the name. */
417 strcpy (name
, dbus_bus_get_unique_name (connection
));
419 xsignal1 (Qdbus_error
, build_string ("No unique name available"));
422 return build_string (name
);
425 DEFUN ("dbus-call-method", Fdbus_call_method
, Sdbus_call_method
, 5, MANY
, 0,
426 doc
: /* Call METHOD on the D-Bus BUS.
428 BUS is either the symbol `:system' or the symbol `:session'.
430 SERVICE is the D-Bus service name to be used. PATH is the D-Bus
431 object path SERVICE is registered at. INTERFACE is an interface
432 offered by SERVICE. It must provide METHOD.
434 All other arguments ARGS are passed to METHOD as arguments. They are
435 converted into D-Bus types via the following rules:
437 t and nil => DBUS_TYPE_BOOLEAN
438 number => DBUS_TYPE_UINT32
439 integer => DBUS_TYPE_INT32
440 float => DBUS_TYPE_DOUBLE
441 string => DBUS_TYPE_STRING
443 Other Lisp objects are not supported as input arguments of METHOD.
445 `dbus-call-method' returns the resulting values of METHOD as a list of
446 Lisp objects. The type conversion happens the other direction as for
447 input arguments. Additionally to the types supported for input
448 arguments, the D-Bus compound types DBUS_TYPE_ARRAY, DBUS_TYPE_VARIANT,
449 DBUS_TYPE_STRUCT and DBUS_TYPE_DICT_ENTRY are accepted. All of them
450 are converted into a list of Lisp objects which correspond to the
451 elements of the D-Bus container. Example:
454 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
455 "org.gnome.seahorse.Keys" "GetKeyField"
456 "openpgp:657984B8C7A966DD" "simple-name")
458 => (t ("Philip R. Zimmermann"))
460 If the result of the METHOD call is just one value, the converted Lisp
461 object is returned instead of a list containing this single Lisp object.
464 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
465 "org.freedesktop.Hal.Device" "GetPropertyString"
466 "system.kernel.machine")
470 usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &rest ARGS) */)
473 register Lisp_Object
*args
;
475 Lisp_Object bus
, service
, path
, interface
, method
;
477 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
478 DBusConnection
*connection
;
479 DBusMessage
*dmessage
;
481 DBusMessageIter iter
;
487 /* Check parameters. */
495 CHECK_STRING (service
);
497 CHECK_STRING (interface
);
498 CHECK_STRING (method
);
499 GCPRO5 (bus
, service
, path
, interface
, method
);
501 XD_DEBUG_MESSAGE ("%s %s %s %s",
507 /* Open a connection to the bus. */
508 connection
= xd_initialize (bus
);
510 /* Create the message. */
511 dmessage
= dbus_message_new_method_call ((char *) SDATA (service
),
512 (char *) SDATA (path
),
513 (char *) SDATA (interface
),
514 (char *) SDATA (method
));
515 if (dmessage
== NULL
)
518 xsignal1 (Qdbus_error
, build_string ("Unable to create a new message"));
523 /* Initialize parameter list of message. */
524 dbus_message_iter_init_append (dmessage
, &iter
);
526 /* Append parameters to the message. */
527 for (i
= 5; i
< nargs
; ++i
)
530 XD_DEBUG_VALID_LISP_OBJECT_P (args
[i
]);
531 XD_DEBUG_MESSAGE ("Parameter%d %s",
533 SDATA (format2 ("%s", args
[i
], Qnil
)));
535 dtype
= XD_LISP_OBJECT_TO_DBUS_TYPE (args
[i
]);
536 if (dtype
== DBUS_TYPE_INVALID
)
537 xsignal2 (Qdbus_error
, build_string ("Not a valid argument"), args
[i
]);
539 if (SYMBOLP (args
[i
])
540 && (strncmp (SDATA (XSYMBOL (args
[i
])->xname
), ":", 1) == 0))
543 xd_append_arg (dtype
, args
[i
], &iter
);
546 /* Send the message. */
547 dbus_error_init (&derror
);
548 reply
= dbus_connection_send_with_reply_and_block (connection
,
553 if (dbus_error_is_set (&derror
))
557 xsignal1 (Qdbus_error
, build_string ("No reply"));
559 XD_DEBUG_MESSAGE ("Message sent");
561 /* Collect the results. */
565 if (!dbus_message_iter_init (reply
, &iter
))
568 xsignal1 (Qdbus_error
, build_string ("Cannot read reply"));
571 /* Loop over the parameters of the D-Bus reply message. Construct a
572 Lisp list, which is returned by `dbus-call-method'. */
573 while ((dtype
= dbus_message_iter_get_arg_type (&iter
)) != DBUS_TYPE_INVALID
)
575 result
= Fcons (xd_retrieve_arg (dtype
, &iter
), result
);
576 dbus_message_iter_next (&iter
);
580 dbus_message_unref (dmessage
);
581 dbus_message_unref (reply
);
583 /* Return the result. If there is only one single Lisp object,
584 return it as-it-is, otherwise return the reversed list. */
585 if (XUINT (Flength (result
)) == 1)
586 RETURN_UNGCPRO (XCAR (result
));
588 RETURN_UNGCPRO (Fnreverse (result
));
591 DEFUN ("dbus-send-signal", Fdbus_send_signal
, Sdbus_send_signal
, 5, MANY
, 0,
592 doc
: /* Send signal SIGNAL on the D-Bus BUS.
594 BUS is either the symbol `:system' or the symbol `:session'.
596 SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
597 D-Bus object path SERVICE is registered at. INTERFACE is an interface
598 offered by SERVICE. It must provide signal SIGNAL.
600 All other arguments ARGS are passed to SIGNAL as arguments. They are
601 converted into D-Bus types via the following rules:
603 t and nil => DBUS_TYPE_BOOLEAN
604 number => DBUS_TYPE_UINT32
605 integer => DBUS_TYPE_INT32
606 float => DBUS_TYPE_DOUBLE
607 string => DBUS_TYPE_STRING
609 Other Lisp objects are not supported as arguments of SIGNAL.
614 :session "org.gnu.Emacs" "/org/gnu/Emacs"
615 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
617 usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
620 register Lisp_Object
*args
;
622 Lisp_Object bus
, service
, path
, interface
, signal
;
623 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
;
624 DBusConnection
*connection
;
625 DBusMessage
*dmessage
;
626 DBusMessageIter iter
;
631 /* Check parameters. */
639 CHECK_STRING (service
);
641 CHECK_STRING (interface
);
642 CHECK_STRING (signal
);
643 GCPRO5 (bus
, service
, path
, interface
, signal
);
645 XD_DEBUG_MESSAGE ("%s %s %s %s",
651 /* Open a connection to the bus. */
652 connection
= xd_initialize (bus
);
654 /* Create the message. */
655 dmessage
= dbus_message_new_signal ((char *) SDATA (path
),
656 (char *) SDATA (interface
),
657 (char *) SDATA (signal
));
658 if (dmessage
== NULL
)
661 xsignal1 (Qdbus_error
, build_string ("Unable to create a new message"));
666 /* Initialize parameter list of message. */
667 dbus_message_iter_init_append (dmessage
, &iter
);
669 /* Append parameters to the message. */
670 for (i
= 5; i
< nargs
; ++i
)
672 XD_DEBUG_VALID_LISP_OBJECT_P (args
[i
]);
673 XD_DEBUG_MESSAGE ("Parameter%d %s",
675 SDATA (format2 ("%s", args
[i
], Qnil
)));
677 dtype
= XD_LISP_OBJECT_TO_DBUS_TYPE (args
[i
]);
678 if (dtype
== DBUS_TYPE_INVALID
)
679 xsignal2 (Qdbus_error
, build_string ("Not a valid argument"), args
[i
]);
681 if (SYMBOLP (args
[i
])
682 && (strncmp (SDATA (XSYMBOL (args
[i
])->xname
), ":", 1) == 0))
685 xd_append_arg (dtype
, args
[i
], &iter
);
688 /* Send the message. The message is just added to the outgoing
690 if (!dbus_connection_send (connection
, dmessage
, NULL
))
691 xsignal1 (Qdbus_error
, build_string ("Cannot send message"));
693 /* Flush connection to ensure the message is handled. */
694 dbus_connection_flush (connection
);
696 XD_DEBUG_MESSAGE ("Signal sent");
699 dbus_message_unref (dmessage
);
705 /* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
706 symbol, either :system or :session. */
708 xd_read_message (bus
)
711 Lisp_Object args
, key
, value
;
713 static struct input_event event
;
714 DBusConnection
*connection
;
715 DBusMessage
*dmessage
;
716 DBusMessageIter iter
;
718 char uname
[DBUS_MAXIMUM_NAME_LENGTH
];
719 char path
[DBUS_MAXIMUM_MATCH_RULE_LENGTH
]; /* Unlimited in D-Bus spec. */
720 char interface
[DBUS_MAXIMUM_NAME_LENGTH
];
721 char member
[DBUS_MAXIMUM_NAME_LENGTH
];
723 /* Open a connection to the bus. */
724 connection
= xd_initialize (bus
);
726 /* Non blocking read of the next available message. */
727 dbus_connection_read_write (connection
, 0);
728 dmessage
= dbus_connection_pop_message (connection
);
730 /* Return if there is no queued message. */
731 if (dmessage
== NULL
)
734 XD_DEBUG_MESSAGE ("Event received");
736 /* Collect the parameters. */
740 if (!dbus_message_iter_init (dmessage
, &iter
))
743 XD_DEBUG_MESSAGE ("Cannot read event");
747 /* Loop over the resulting parameters. Construct a list. */
748 while ((dtype
= dbus_message_iter_get_arg_type (&iter
)) != DBUS_TYPE_INVALID
)
750 args
= Fcons (xd_retrieve_arg (dtype
, &iter
), args
);
751 dbus_message_iter_next (&iter
);
754 /* The arguments are stored in reverse order. Reorder them. */
755 args
= Fnreverse (args
);
757 /* Read unique name, object path, interface and member from the
759 strcpy (uname
, dbus_message_get_sender (dmessage
));
760 strcpy (path
, dbus_message_get_path (dmessage
));
761 strcpy (interface
, dbus_message_get_interface (dmessage
));
762 strcpy (member
, dbus_message_get_member (dmessage
));
764 /* Search for a registered function of the message. */
765 key
= list3 (bus
, build_string (interface
), build_string (member
));
766 value
= Fgethash (key
, Vdbus_registered_functions_table
, Qnil
);
768 /* Loop over the registered functions. Construct an event. */
769 while (!NILP (value
))
772 /* key has the structure (UNAME SERVICE PATH HANDLER). */
774 || (NILP (XCAR (key
)))
775 || (strcmp (uname
, SDATA (XCAR (key
))) == 0))
777 || (NILP (XCAR (XCDR (XCDR (key
)))))
778 || (strcmp (path
, SDATA (XCAR (XCDR (XCDR (key
))))) == 0))
779 && (!NILP (XCAR (XCDR (XCDR (XCDR (key
)))))))
782 event
.kind
= DBUS_EVENT
;
783 event
.frame_or_window
= Qnil
;
784 event
.arg
= Fcons (XCAR (XCDR (XCDR (XCDR (key
)))), args
);
786 /* Add uname, path, interface and member to the event. */
787 event
.arg
= Fcons ((member
== NULL
? Qnil
: build_string (member
)),
789 event
.arg
= Fcons ((interface
== NULL
790 ? Qnil
: build_string (interface
)),
792 event
.arg
= Fcons ((path
== NULL
? Qnil
: build_string (path
)),
794 event
.arg
= Fcons ((uname
== NULL
? Qnil
: build_string (uname
)),
797 /* Add the bus symbol to the event. */
798 event
.arg
= Fcons (bus
, event
.arg
);
800 /* Store it into the input event queue. */
801 kbd_buffer_store_event (&event
);
803 value
= XCDR (value
);
807 dbus_message_unref (dmessage
);
811 /* Read queued incoming messages from the system and session buses. */
813 xd_read_queued_messages ()
816 /* Vdbus_registered_functions_table will be initialized as hash
817 table in dbus.el. When this package isn't loaded yet, it doesn't
818 make sense to handle D-Bus messages. Furthermore, we ignore all
819 Lisp errors during the call. */
820 if (HASH_TABLE_P (Vdbus_registered_functions_table
))
822 internal_condition_case_1 (xd_read_message
, QCdbus_system_bus
,
824 internal_condition_case_1 (xd_read_message
, QCdbus_session_bus
,
829 DEFUN ("dbus-register-signal", Fdbus_register_signal
, Sdbus_register_signal
,
831 doc
: /* Register for signal SIGNAL on the D-Bus BUS.
833 BUS is either the symbol `:system' or the symbol `:session'.
835 SERVICE is the D-Bus service name used by the sending D-Bus object.
836 It can be either a known name or the unique name of the D-Bus object
837 sending the signal. When SERVICE is nil, related signals from all
838 D-Bus objects shall be accepted.
840 PATH is the D-Bus object path SERVICE is registered. It can also be
841 nil if the path name of incoming signals shall not be checked.
843 INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
844 HANDLER is a Lisp function to be called when the signal is received.
845 It must accept as arguments the values SIGNAL is sending. INTERFACE,
846 SIGNAL and HANDLER must not be nil. Example:
848 \(defun my-signal-handler (device)
849 (message "Device %s added" device))
851 \(dbus-register-signal
852 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
853 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
855 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
856 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
858 `dbus-register-signal' returns an object, which can be used in
859 `dbus-unregister-signal' for removing the registration. */)
860 (bus
, service
, path
, interface
, signal
, handler
)
861 Lisp_Object bus
, service
, path
, interface
, signal
, handler
;
863 Lisp_Object uname
, key
, value
;
864 DBusConnection
*connection
;
865 char rule
[DBUS_MAXIMUM_MATCH_RULE_LENGTH
];
868 /* Check parameters. */
870 if (!NILP (service
)) CHECK_STRING (service
);
871 if (!NILP (path
)) CHECK_STRING (path
);
872 CHECK_STRING (interface
);
873 CHECK_STRING (signal
);
876 /* Retrieve unique name of service. If service is a known name, we
877 will register for the corresponding unique name, if any. Signals
878 are sent always with the unique name as sender. Note: the unique
879 name of "org.freedesktop.DBus" is that string itself. */
880 if ((!NILP (service
))
881 && (strlen (SDATA (service
)) > 0)
882 && (strcmp (SDATA (service
), DBUS_SERVICE_DBUS
) != 0)
883 && (strncmp (SDATA (service
), ":", 1) != 0))
885 uname
= call2 (intern ("dbus-get-name-owner"), bus
, service
);
886 /* When there is no unique name, we mark it with an empty
889 uname
= build_string ("");
894 /* Create a matching rule if the unique name exists (when no
896 if (NILP (uname
) || (strlen (SDATA (uname
)) > 0))
898 /* Open a connection to the bus. */
899 connection
= xd_initialize (bus
);
901 /* Create a rule to receive related signals. */
903 "type='signal',interface='%s',member='%s'",
907 /* Add unique name and path to the rule if they are non-nil. */
909 sprintf (rule
, "%s,sender='%s'", rule
, SDATA (uname
));
912 sprintf (rule
, "%s,path='%s'", rule
, SDATA (path
));
914 /* Add the rule to the bus. */
915 dbus_error_init (&derror
);
916 dbus_bus_add_match (connection
, rule
, &derror
);
917 if (dbus_error_is_set (&derror
))
920 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule
);
923 /* Create a hash table entry. */
924 key
= list3 (bus
, interface
, signal
);
925 value
= Fgethash (key
, Vdbus_registered_functions_table
, Qnil
);
927 if (NILP (Fmember (list4 (uname
, service
, path
, handler
), value
)))
929 Fcons (list4 (uname
, service
, path
, handler
), value
),
930 Vdbus_registered_functions_table
);
933 return list2 (key
, list3 (service
, path
, handler
));
936 DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal
, Sdbus_unregister_signal
,
938 doc
: /* Unregister OBJECT from the D-Bus.
939 OBJECT must be the result of a preceding `dbus-register-signal' call. */)
946 /* Check parameter. */
947 CONSP (object
) && (!NILP (XCAR (object
))) && CONSP (XCDR (object
));
949 /* Find the corresponding entry in the hash table. */
950 value
= Fgethash (XCAR (object
), Vdbus_registered_functions_table
, Qnil
);
952 /* Loop over the registered functions. */
953 while (!NILP (value
))
957 /* (car value) has the structure (UNAME SERVICE PATH HANDLER).
958 (cdr object) has the structure ((SERVICE PATH HANDLER) ...). */
959 if (!NILP (Fequal (XCDR (XCAR (value
)), XCAR (XCDR (object
)))))
961 /* Compute new hash value. */
962 value
= Fdelete (XCAR (value
),
963 Fgethash (XCAR (object
),
964 Vdbus_registered_functions_table
, Qnil
));
966 Fremhash (XCAR (object
), Vdbus_registered_functions_table
);
968 Fputhash (XCAR (object
), value
, Vdbus_registered_functions_table
);
972 value
= XCDR (value
);
984 Qdbus_get_unique_name
= intern ("dbus-get-unique-name");
985 staticpro (&Qdbus_get_unique_name
);
986 defsubr (&Sdbus_get_unique_name
);
988 Qdbus_call_method
= intern ("dbus-call-method");
989 staticpro (&Qdbus_call_method
);
990 defsubr (&Sdbus_call_method
);
992 Qdbus_send_signal
= intern ("dbus-send-signal");
993 staticpro (&Qdbus_send_signal
);
994 defsubr (&Sdbus_send_signal
);
996 Qdbus_register_signal
= intern ("dbus-register-signal");
997 staticpro (&Qdbus_register_signal
);
998 defsubr (&Sdbus_register_signal
);
1000 Qdbus_unregister_signal
= intern ("dbus-unregister-signal");
1001 staticpro (&Qdbus_unregister_signal
);
1002 defsubr (&Sdbus_unregister_signal
);
1004 Qdbus_error
= intern ("dbus-error");
1005 staticpro (&Qdbus_error
);
1006 Fput (Qdbus_error
, Qerror_conditions
,
1007 list2 (Qdbus_error
, Qerror
));
1008 Fput (Qdbus_error
, Qerror_message
,
1009 build_string ("D-Bus error"));
1011 QCdbus_system_bus
= intern (":system");
1012 staticpro (&QCdbus_system_bus
);
1014 QCdbus_session_bus
= intern (":session");
1015 staticpro (&QCdbus_session_bus
);
1017 QCdbus_type_byte
= intern (":byte");
1018 staticpro (&QCdbus_type_byte
);
1020 QCdbus_type_boolean
= intern (":boolean");
1021 staticpro (&QCdbus_type_boolean
);
1023 QCdbus_type_int16
= intern (":int16");
1024 staticpro (&QCdbus_type_int16
);
1026 QCdbus_type_uint16
= intern (":uint16");
1027 staticpro (&QCdbus_type_uint16
);
1029 QCdbus_type_int32
= intern (":int32");
1030 staticpro (&QCdbus_type_int32
);
1032 QCdbus_type_uint32
= intern (":uint32");
1033 staticpro (&QCdbus_type_uint32
);
1035 QCdbus_type_int64
= intern (":int64");
1036 staticpro (&QCdbus_type_int64
);
1038 QCdbus_type_uint64
= intern (":uint64");
1039 staticpro (&QCdbus_type_uint64
);
1041 QCdbus_type_double
= intern (":double");
1042 staticpro (&QCdbus_type_double
);
1044 QCdbus_type_string
= intern (":string");
1045 staticpro (&QCdbus_type_string
);
1047 QCdbus_type_object_path
= intern (":object-path");
1048 staticpro (&QCdbus_type_object_path
);
1050 QCdbus_type_signature
= intern (":signature");
1051 staticpro (&QCdbus_type_signature
);
1053 QCdbus_type_array
= intern (":array");
1054 staticpro (&QCdbus_type_array
);
1056 QCdbus_type_variant
= intern (":variant");
1057 staticpro (&QCdbus_type_variant
);
1059 QCdbus_type_struct
= intern (":struct");
1060 staticpro (&QCdbus_type_struct
);
1062 QCdbus_type_dict_entry
= intern (":dict-entry");
1063 staticpro (&QCdbus_type_dict_entry
);
1065 DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table
,
1066 doc
: /* Hash table of registered functions for D-Bus.
1067 The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is
1068 either the symbol `:system' or the symbol `:session'. INTERFACE is a
1069 string which denotes a D-Bus interface, and MEMBER, also a string, is
1070 either a method or a signal INTERFACE is offering. All arguments but
1071 BUS must not be nil.
1073 The value in the hash table is a list of quadruple lists
1074 \((UNAME SERVICE PATH HANDLER) (UNAME SERVICE PATH HANDLER) ...).
1075 SERVICE is the service name as registered, UNAME is the corresponding
1076 unique name. PATH is the object path of the sending object. All of
1077 them can be nil, which means a wildcard then. HANDLER is the function
1078 to be called when a D-Bus message, which matches the key criteria,
1080 /* We initialize Vdbus_registered_functions_table in dbus.el,
1081 because we need to define a hash table function first. */
1082 Vdbus_registered_functions_table
= Qnil
;
1084 DEFVAR_LISP ("dbus-debug", &Vdbus_debug
,
1085 doc
: /* If non-nil, debug messages of D-Bus bindings are raised. */);
1092 Fprovide (intern ("dbusbind"), Qnil
);
1096 #endif /* HAVE_DBUS */
1098 /* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
1099 (do not change this comment) */