; * lisp/ldefs-boot.el: Update.
[emacs.git] / src / dbusbind.c
blobfcb58f744895e674f3460fbaa0da93d44b848272
1 /* Elisp bindings for D-Bus.
2 Copyright (C) 2007-2019 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 of the License, or (at
9 your option) any later version.
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. If not, see <https://www.gnu.org/licenses/>. */
19 #include <config.h>
21 #ifdef HAVE_DBUS
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <dbus/dbus.h>
26 #include "lisp.h"
27 #include "termhooks.h"
28 #include "keyboard.h"
29 #include "process.h"
31 #ifndef DBUS_NUM_MESSAGE_TYPES
32 #define DBUS_NUM_MESSAGE_TYPES 5
33 #endif
36 /* Some platforms define the symbol "interface", but we want to use it
37 * as a variable name below. */
39 #ifdef interface
40 #undef interface
41 #endif
44 /* Alist of D-Bus buses we are polling for messages.
45 The key is the symbol or string of the bus, and the value is the
46 connection address. */
47 static Lisp_Object xd_registered_buses;
49 /* Whether we are reading a D-Bus event. */
50 static bool xd_in_read_queued_messages = 0;
53 /* We use "xd_" and "XD_" as prefix for all internal symbols, because
54 we don't want to poison other namespaces with "dbus_". */
56 /* Raise a signal. If we are reading events, we cannot signal; we
57 throw to xd_read_queued_messages then. */
58 #define XD_SIGNAL1(arg) \
59 do { \
60 if (xd_in_read_queued_messages) \
61 Fthrow (Qdbus_error, Qnil); \
62 else \
63 xsignal1 (Qdbus_error, arg); \
64 } while (0)
66 #define XD_SIGNAL2(arg1, arg2) \
67 do { \
68 if (xd_in_read_queued_messages) \
69 Fthrow (Qdbus_error, Qnil); \
70 else \
71 xsignal2 (Qdbus_error, arg1, arg2); \
72 } while (0)
74 #define XD_SIGNAL3(arg1, arg2, arg3) \
75 do { \
76 if (xd_in_read_queued_messages) \
77 Fthrow (Qdbus_error, Qnil); \
78 else \
79 xsignal3 (Qdbus_error, arg1, arg2, arg3); \
80 } while (0)
82 /* Raise a Lisp error from a D-Bus ERROR. */
83 #define XD_ERROR(error) \
84 do { \
85 /* Remove the trailing newline. */ \
86 char const *mess = error.message; \
87 char const *nl = strchr (mess, '\n'); \
88 Lisp_Object err = make_string (mess, nl ? nl - mess : strlen (mess)); \
89 dbus_error_free (&error); \
90 XD_SIGNAL1 (err); \
91 } while (0)
93 /* Macros for debugging. In order to enable them, build with
94 "make MYCPPFLAGS='-DDBUS_DEBUG'". */
95 #ifdef DBUS_DEBUG
96 #define XD_DEBUG_MESSAGE(...) \
97 do { \
98 char s[1024]; \
99 snprintf (s, sizeof s, __VA_ARGS__); \
100 if (!noninteractive) \
101 printf ("%s: %s\n", __func__, s); \
102 message ("%s: %s", __func__, s); \
103 } while (0)
104 #define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
105 do { \
106 if (!valid_lisp_object_p (object)) \
108 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
109 XD_SIGNAL1 (build_string ("Assertion failure")); \
111 } while (0)
113 #else /* !DBUS_DEBUG */
114 # define XD_DEBUG_MESSAGE(...) \
115 do { \
116 if (!NILP (Vdbus_debug)) \
118 char s[1024]; \
119 snprintf (s, sizeof s, __VA_ARGS__); \
120 message ("%s: %s", __func__, s); \
122 } while (0)
123 # define XD_DEBUG_VALID_LISP_OBJECT_P(object)
124 #endif
126 /* Check whether TYPE is a basic DBusType. */
127 #ifdef HAVE_DBUS_TYPE_IS_VALID
128 #define XD_BASIC_DBUS_TYPE(type) \
129 (dbus_type_is_valid (type) && dbus_type_is_basic (type))
130 #else
131 #ifdef DBUS_TYPE_UNIX_FD
132 #define XD_BASIC_DBUS_TYPE(type) \
133 ((type == DBUS_TYPE_BYTE) \
134 || (type == DBUS_TYPE_BOOLEAN) \
135 || (type == DBUS_TYPE_INT16) \
136 || (type == DBUS_TYPE_UINT16) \
137 || (type == DBUS_TYPE_INT32) \
138 || (type == DBUS_TYPE_UINT32) \
139 || (type == DBUS_TYPE_INT64) \
140 || (type == DBUS_TYPE_UINT64) \
141 || (type == DBUS_TYPE_DOUBLE) \
142 || (type == DBUS_TYPE_STRING) \
143 || (type == DBUS_TYPE_OBJECT_PATH) \
144 || (type == DBUS_TYPE_SIGNATURE) \
145 || (type == DBUS_TYPE_UNIX_FD))
146 #else
147 #define XD_BASIC_DBUS_TYPE(type) \
148 ((type == DBUS_TYPE_BYTE) \
149 || (type == DBUS_TYPE_BOOLEAN) \
150 || (type == DBUS_TYPE_INT16) \
151 || (type == DBUS_TYPE_UINT16) \
152 || (type == DBUS_TYPE_INT32) \
153 || (type == DBUS_TYPE_UINT32) \
154 || (type == DBUS_TYPE_INT64) \
155 || (type == DBUS_TYPE_UINT64) \
156 || (type == DBUS_TYPE_DOUBLE) \
157 || (type == DBUS_TYPE_STRING) \
158 || (type == DBUS_TYPE_OBJECT_PATH) \
159 || (type == DBUS_TYPE_SIGNATURE))
160 #endif
161 #endif
163 /* This was a macro. On Solaris 2.11 it was said to compile for
164 hours, when optimization is enabled. So we have transferred it into
165 a function. */
166 /* Determine the DBusType of a given Lisp symbol. OBJECT must be one
167 of the predefined D-Bus type symbols. */
168 static int
169 xd_symbol_to_dbus_type (Lisp_Object object)
171 return
172 (EQ (object, QCbyte) ? DBUS_TYPE_BYTE
173 : EQ (object, QCboolean) ? DBUS_TYPE_BOOLEAN
174 : EQ (object, QCint16) ? DBUS_TYPE_INT16
175 : EQ (object, QCuint16) ? DBUS_TYPE_UINT16
176 : EQ (object, QCint32) ? DBUS_TYPE_INT32
177 : EQ (object, QCuint32) ? DBUS_TYPE_UINT32
178 : EQ (object, QCint64) ? DBUS_TYPE_INT64
179 : EQ (object, QCuint64) ? DBUS_TYPE_UINT64
180 : EQ (object, QCdouble) ? DBUS_TYPE_DOUBLE
181 : EQ (object, QCstring) ? DBUS_TYPE_STRING
182 : EQ (object, QCobject_path) ? DBUS_TYPE_OBJECT_PATH
183 : EQ (object, QCsignature) ? DBUS_TYPE_SIGNATURE
184 #ifdef DBUS_TYPE_UNIX_FD
185 : EQ (object, QCunix_fd) ? DBUS_TYPE_UNIX_FD
186 #endif
187 : EQ (object, QCarray) ? DBUS_TYPE_ARRAY
188 : EQ (object, QCvariant) ? DBUS_TYPE_VARIANT
189 : EQ (object, QCstruct) ? DBUS_TYPE_STRUCT
190 : EQ (object, QCdict_entry) ? DBUS_TYPE_DICT_ENTRY
191 : DBUS_TYPE_INVALID);
194 /* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
195 #define XD_DBUS_TYPE_P(object) \
196 (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
198 /* Determine the DBusType of a given Lisp OBJECT. It is used to
199 convert Lisp objects, being arguments of `dbus-call-method' or
200 `dbus-send-signal', into corresponding C values appended as
201 arguments to a D-Bus message. */
202 #define XD_OBJECT_TO_DBUS_TYPE(object) \
203 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
204 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
205 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
206 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
207 : (STRINGP (object)) ? DBUS_TYPE_STRING \
208 : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
209 : (CONSP (object)) \
210 ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
211 ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
212 ? DBUS_TYPE_ARRAY \
213 : xd_symbol_to_dbus_type (CAR_SAFE (object))) \
214 : DBUS_TYPE_ARRAY) \
215 : DBUS_TYPE_INVALID)
217 /* Return a list pointer which does not have a Lisp symbol as car. */
218 #define XD_NEXT_VALUE(object) \
219 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
221 /* Transform the message type to its string representation for debug
222 messages. */
223 #define XD_MESSAGE_TYPE_TO_STRING(mtype) \
224 ((mtype == DBUS_MESSAGE_TYPE_INVALID) \
225 ? "DBUS_MESSAGE_TYPE_INVALID" \
226 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) \
227 ? "DBUS_MESSAGE_TYPE_METHOD_CALL" \
228 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN) \
229 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN" \
230 : (mtype == DBUS_MESSAGE_TYPE_ERROR) \
231 ? "DBUS_MESSAGE_TYPE_ERROR" \
232 : "DBUS_MESSAGE_TYPE_SIGNAL")
234 /* Transform the object to its string representation for debug
235 messages. */
236 static char *
237 XD_OBJECT_TO_STRING (Lisp_Object object)
239 AUTO_STRING (format, "%s");
240 return SSDATA (CALLN (Fformat, format, object));
243 #define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
244 do { \
245 char const *session_bus_address = getenv ("DBUS_SESSION_BUS_ADDRESS"); \
246 if (STRINGP (bus)) \
248 DBusAddressEntry **entries; \
249 int len; \
250 DBusError derror; \
251 dbus_error_init (&derror); \
252 if (!dbus_parse_address (SSDATA (bus), &entries, &len, &derror)) \
253 XD_ERROR (derror); \
254 /* Cleanup. */ \
255 dbus_error_free (&derror); \
256 dbus_address_entries_free (entries); \
257 /* Canonicalize session bus address. */ \
258 if ((session_bus_address != NULL) \
259 && (!NILP (Fstring_equal \
260 (bus, build_string (session_bus_address))))) \
261 bus = QCsession; \
264 else \
266 CHECK_SYMBOL (bus); \
267 if (!(EQ (bus, QCsystem) || EQ (bus, QCsession))) \
268 XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \
269 /* We do not want to have an autolaunch for the session bus. */ \
270 if (EQ (bus, QCsession) && session_bus_address == NULL) \
271 XD_SIGNAL2 (build_string ("No connection to bus"), bus); \
273 } while (0)
275 #if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
276 || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER)
277 #define XD_DBUS_VALIDATE_OBJECT(object, func) \
278 do { \
279 if (!NILP (object)) \
281 DBusError derror; \
282 CHECK_STRING (object); \
283 dbus_error_init (&derror); \
284 if (!func (SSDATA (object), &derror)) \
285 XD_ERROR (derror); \
286 /* Cleanup. */ \
287 dbus_error_free (&derror); \
289 } while (0)
290 #endif
292 #if HAVE_DBUS_VALIDATE_BUS_NAME
293 #define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
294 XD_DBUS_VALIDATE_OBJECT(bus_name, dbus_validate_bus_name);
295 #else
296 #define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
297 if (!NILP (bus_name)) CHECK_STRING (bus_name);
298 #endif
300 #if HAVE_DBUS_VALIDATE_PATH
301 #define XD_DBUS_VALIDATE_PATH(path) \
302 XD_DBUS_VALIDATE_OBJECT(path, dbus_validate_path);
303 #else
304 #define XD_DBUS_VALIDATE_PATH(path) \
305 if (!NILP (path)) CHECK_STRING (path);
306 #endif
308 #if HAVE_DBUS_VALIDATE_INTERFACE
309 #define XD_DBUS_VALIDATE_INTERFACE(interface) \
310 XD_DBUS_VALIDATE_OBJECT(interface, dbus_validate_interface);
311 #else
312 #define XD_DBUS_VALIDATE_INTERFACE(interface) \
313 if (!NILP (interface)) CHECK_STRING (interface);
314 #endif
316 #if HAVE_DBUS_VALIDATE_MEMBER
317 #define XD_DBUS_VALIDATE_MEMBER(member) \
318 XD_DBUS_VALIDATE_OBJECT(member, dbus_validate_member);
319 #else
320 #define XD_DBUS_VALIDATE_MEMBER(member) \
321 if (!NILP (member)) CHECK_STRING (member);
322 #endif
324 /* Append to SIGNATURE a copy of X, making sure SIGNATURE does
325 not become too long. */
326 static void
327 xd_signature_cat (char *signature, char const *x)
329 ptrdiff_t siglen = strlen (signature);
330 ptrdiff_t xlen = strlen (x);
331 if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
332 string_overflow ();
333 strcpy (signature + siglen, x);
336 /* Compute SIGNATURE of OBJECT. It must have a form that it can be
337 used in dbus_message_iter_open_container. DTYPE is the DBusType
338 the object is related to. It is passed as argument, because it
339 cannot be detected in basic type objects, when they are preceded by
340 a type symbol. PARENT_TYPE is the DBusType of a container this
341 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
342 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
343 static void
344 xd_signature (char *signature, int dtype, int parent_type, Lisp_Object object)
346 int subtype;
347 Lisp_Object elt;
348 char const *subsig;
349 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
351 elt = object;
353 switch (dtype)
355 case DBUS_TYPE_BYTE:
356 case DBUS_TYPE_UINT16:
357 CHECK_NATNUM (object);
358 sprintf (signature, "%c", dtype);
359 break;
361 case DBUS_TYPE_BOOLEAN:
362 if (!EQ (object, Qt) && !EQ (object, Qnil))
363 wrong_type_argument (intern ("booleanp"), object);
364 sprintf (signature, "%c", dtype);
365 break;
367 case DBUS_TYPE_INT16:
368 CHECK_NUMBER (object);
369 sprintf (signature, "%c", dtype);
370 break;
372 case DBUS_TYPE_UINT32:
373 case DBUS_TYPE_UINT64:
374 #ifdef DBUS_TYPE_UNIX_FD
375 case DBUS_TYPE_UNIX_FD:
376 #endif
377 case DBUS_TYPE_INT32:
378 case DBUS_TYPE_INT64:
379 case DBUS_TYPE_DOUBLE:
380 CHECK_NUMBER_OR_FLOAT (object);
381 sprintf (signature, "%c", dtype);
382 break;
384 case DBUS_TYPE_STRING:
385 case DBUS_TYPE_OBJECT_PATH:
386 case DBUS_TYPE_SIGNATURE:
387 CHECK_STRING (object);
388 sprintf (signature, "%c", dtype);
389 break;
391 case DBUS_TYPE_ARRAY:
392 /* Check that all list elements have the same D-Bus type. For
393 complex element types, we just check the container type, not
394 the whole element's signature. */
395 CHECK_CONS (object);
397 /* Type symbol is optional. */
398 if (EQ (QCarray, CAR_SAFE (elt)))
399 elt = XD_NEXT_VALUE (elt);
401 /* If the array is empty, DBUS_TYPE_STRING is the default
402 element type. */
403 if (NILP (elt))
405 subtype = DBUS_TYPE_STRING;
406 subsig = DBUS_TYPE_STRING_AS_STRING;
408 else
410 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
411 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
412 subsig = x;
415 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
416 only element, the value of this element is used as the
417 array's element signature. */
418 if ((subtype == DBUS_TYPE_SIGNATURE)
419 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
420 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
421 subsig = SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt)));
423 while (!NILP (elt))
425 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
426 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
427 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
430 signature[0] = dtype;
431 signature[1] = '\0';
432 xd_signature_cat (signature, subsig);
433 break;
435 case DBUS_TYPE_VARIANT:
436 /* Check that there is exactly one list element. */
437 CHECK_CONS (object);
439 elt = XD_NEXT_VALUE (elt);
440 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
441 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
443 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
444 wrong_type_argument (intern ("D-Bus"),
445 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
447 sprintf (signature, "%c", dtype);
448 break;
450 case DBUS_TYPE_STRUCT:
451 /* A struct list might contain any number of elements with
452 different types. No further check needed. */
453 CHECK_CONS (object);
455 elt = XD_NEXT_VALUE (elt);
457 /* Compose the signature from the elements. It is enclosed by
458 parentheses. */
459 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
460 while (!NILP (elt))
462 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
463 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
464 xd_signature_cat (signature, x);
465 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
467 xd_signature_cat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
468 break;
470 case DBUS_TYPE_DICT_ENTRY:
471 /* Check that there are exactly two list elements, and the first
472 one is of basic type. The dictionary entry itself must be an
473 element of an array. */
474 CHECK_CONS (object);
476 /* Check the parent object type. */
477 if (parent_type != DBUS_TYPE_ARRAY)
478 wrong_type_argument (intern ("D-Bus"), object);
480 /* Compose the signature from the elements. It is enclosed by
481 curly braces. */
482 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
484 /* First element. */
485 elt = XD_NEXT_VALUE (elt);
486 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
487 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
488 xd_signature_cat (signature, x);
490 if (!XD_BASIC_DBUS_TYPE (subtype))
491 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
493 /* Second element. */
494 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
495 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
496 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
497 xd_signature_cat (signature, x);
499 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
500 wrong_type_argument (intern ("D-Bus"),
501 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
503 /* Closing signature. */
504 xd_signature_cat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
505 break;
507 default:
508 wrong_type_argument (intern ("D-Bus"), object);
511 XD_DEBUG_MESSAGE ("%s", signature);
514 /* Convert X to a signed integer with bounds LO and HI. */
515 static intmax_t
516 xd_extract_signed (Lisp_Object x, intmax_t lo, intmax_t hi)
518 CHECK_NUMBER_OR_FLOAT (x);
519 if (INTEGERP (x))
521 if (lo <= XINT (x) && XINT (x) <= hi)
522 return XINT (x);
524 else
526 double d = XFLOAT_DATA (x);
527 if (lo <= d && d < 1.0 + hi)
529 intmax_t n = d;
530 if (n == d)
531 return n;
534 if (xd_in_read_queued_messages)
535 Fthrow (Qdbus_error, Qnil);
536 else
537 args_out_of_range_3 (x,
538 make_fixnum_or_float (lo),
539 make_fixnum_or_float (hi));
542 /* Convert X to an unsigned integer with bounds 0 and HI. */
543 static uintmax_t
544 xd_extract_unsigned (Lisp_Object x, uintmax_t hi)
546 CHECK_NUMBER_OR_FLOAT (x);
547 if (INTEGERP (x))
549 if (0 <= XINT (x) && XINT (x) <= hi)
550 return XINT (x);
552 else
554 double d = XFLOAT_DATA (x);
555 if (0 <= d && d < 1.0 + hi)
557 uintmax_t n = d;
558 if (n == d)
559 return n;
562 if (xd_in_read_queued_messages)
563 Fthrow (Qdbus_error, Qnil);
564 else
565 args_out_of_range_3 (x, make_number (0), make_fixnum_or_float (hi));
568 /* Append C value, extracted from Lisp OBJECT, to iteration ITER.
569 DTYPE must be a valid DBusType. It is used to convert Lisp
570 objects, being arguments of `dbus-call-method' or
571 `dbus-send-signal', into corresponding C values appended as
572 arguments to a D-Bus message. */
573 static void
574 xd_append_arg (int dtype, Lisp_Object object, DBusMessageIter *iter)
576 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
577 DBusMessageIter subiter;
579 if (XD_BASIC_DBUS_TYPE (dtype))
580 switch (dtype)
582 case DBUS_TYPE_BYTE:
583 CHECK_NATNUM (object);
585 unsigned char val = XFASTINT (object) & 0xFF;
586 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
587 if (!dbus_message_iter_append_basic (iter, dtype, &val))
588 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
589 return;
592 case DBUS_TYPE_BOOLEAN:
594 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
595 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
596 if (!dbus_message_iter_append_basic (iter, dtype, &val))
597 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
598 return;
601 case DBUS_TYPE_INT16:
603 dbus_int16_t val =
604 xd_extract_signed (object,
605 TYPE_MINIMUM (dbus_int16_t),
606 TYPE_MAXIMUM (dbus_int16_t));
607 int pval = val;
608 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
609 if (!dbus_message_iter_append_basic (iter, dtype, &val))
610 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
611 return;
614 case DBUS_TYPE_UINT16:
616 dbus_uint16_t val =
617 xd_extract_unsigned (object,
618 TYPE_MAXIMUM (dbus_uint16_t));
619 unsigned int pval = val;
620 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
621 if (!dbus_message_iter_append_basic (iter, dtype, &val))
622 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
623 return;
626 case DBUS_TYPE_INT32:
628 dbus_int32_t val =
629 xd_extract_signed (object,
630 TYPE_MINIMUM (dbus_int32_t),
631 TYPE_MAXIMUM (dbus_int32_t));
632 int pval = val;
633 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
634 if (!dbus_message_iter_append_basic (iter, dtype, &val))
635 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
636 return;
639 case DBUS_TYPE_UINT32:
640 #ifdef DBUS_TYPE_UNIX_FD
641 case DBUS_TYPE_UNIX_FD:
642 #endif
644 dbus_uint32_t val =
645 xd_extract_unsigned (object,
646 TYPE_MAXIMUM (dbus_uint32_t));
647 unsigned int pval = val;
648 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
649 if (!dbus_message_iter_append_basic (iter, dtype, &val))
650 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
651 return;
654 case DBUS_TYPE_INT64:
656 dbus_int64_t val =
657 xd_extract_signed (object,
658 TYPE_MINIMUM (dbus_int64_t),
659 TYPE_MAXIMUM (dbus_int64_t));
660 printmax_t pval = val;
661 XD_DEBUG_MESSAGE ("%c %"pMd, dtype, pval);
662 if (!dbus_message_iter_append_basic (iter, dtype, &val))
663 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
664 return;
667 case DBUS_TYPE_UINT64:
669 dbus_uint64_t val =
670 xd_extract_unsigned (object,
671 TYPE_MAXIMUM (dbus_uint64_t));
672 uprintmax_t pval = val;
673 XD_DEBUG_MESSAGE ("%c %"pMu, dtype, pval);
674 if (!dbus_message_iter_append_basic (iter, dtype, &val))
675 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
676 return;
679 case DBUS_TYPE_DOUBLE:
681 double val = extract_float (object);
682 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
683 if (!dbus_message_iter_append_basic (iter, dtype, &val))
684 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
685 return;
688 case DBUS_TYPE_STRING:
689 case DBUS_TYPE_OBJECT_PATH:
690 case DBUS_TYPE_SIGNATURE:
691 CHECK_STRING (object);
693 /* We need to send a valid UTF-8 string. We could encode `object'
694 but by not encoding it, we guarantee it's valid utf-8, even if
695 it contains eight-bit-bytes. Of course, you can still send
696 manually-crafted junk by passing a unibyte string. */
697 char *val = SSDATA (object);
698 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
699 if (!dbus_message_iter_append_basic (iter, dtype, &val))
700 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
701 return;
705 else /* Compound types. */
708 /* All compound types except array have a type symbol. For
709 array, it is optional. Skip it. */
710 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
711 object = XD_NEXT_VALUE (object);
713 /* Open new subiteration. */
714 switch (dtype)
716 case DBUS_TYPE_ARRAY:
717 /* An array has only elements of the same type. So it is
718 sufficient to check the first element's signature
719 only. */
721 if (NILP (object))
722 /* If the array is empty, DBUS_TYPE_STRING is the default
723 element type. */
724 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
726 else
727 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
728 the only element, the value of this element is used as
729 the array's element signature. */
730 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
731 == DBUS_TYPE_SIGNATURE)
732 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
733 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
735 lispstpcpy (signature, CAR_SAFE (XD_NEXT_VALUE (object)));
736 object = CDR_SAFE (XD_NEXT_VALUE (object));
739 else
740 xd_signature (signature,
741 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
742 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
744 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
745 XD_OBJECT_TO_STRING (object));
746 if (!dbus_message_iter_open_container (iter, dtype,
747 signature, &subiter))
748 XD_SIGNAL3 (build_string ("Cannot open container"),
749 make_number (dtype), build_string (signature));
750 break;
752 case DBUS_TYPE_VARIANT:
753 /* A variant has just one element. */
754 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
755 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
757 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
758 XD_OBJECT_TO_STRING (object));
759 if (!dbus_message_iter_open_container (iter, dtype,
760 signature, &subiter))
761 XD_SIGNAL3 (build_string ("Cannot open container"),
762 make_number (dtype), build_string (signature));
763 break;
765 case DBUS_TYPE_STRUCT:
766 case DBUS_TYPE_DICT_ENTRY:
767 /* These containers do not require a signature. */
768 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (object));
769 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
770 XD_SIGNAL2 (build_string ("Cannot open container"),
771 make_number (dtype));
772 break;
775 /* Loop over list elements. */
776 while (!NILP (object))
778 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
779 object = XD_NEXT_VALUE (object);
781 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
783 object = CDR_SAFE (object);
786 /* Close the subiteration. */
787 if (!dbus_message_iter_close_container (iter, &subiter))
788 XD_SIGNAL2 (build_string ("Cannot close container"),
789 make_number (dtype));
793 /* Retrieve C value from a DBusMessageIter structure ITER, and return
794 a converted Lisp object. The type DTYPE of the argument of the
795 D-Bus message must be a valid DBusType. Compound D-Bus types
796 result always in a Lisp list. */
797 static Lisp_Object
798 xd_retrieve_arg (int dtype, DBusMessageIter *iter)
801 switch (dtype)
803 case DBUS_TYPE_BYTE:
805 unsigned int val;
806 dbus_message_iter_get_basic (iter, &val);
807 val = val & 0xFF;
808 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
809 return make_number (val);
812 case DBUS_TYPE_BOOLEAN:
814 dbus_bool_t val;
815 dbus_message_iter_get_basic (iter, &val);
816 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
817 return (val == FALSE) ? Qnil : Qt;
820 case DBUS_TYPE_INT16:
822 dbus_int16_t val;
823 int pval;
824 dbus_message_iter_get_basic (iter, &val);
825 pval = val;
826 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
827 return make_number (val);
830 case DBUS_TYPE_UINT16:
832 dbus_uint16_t val;
833 int pval;
834 dbus_message_iter_get_basic (iter, &val);
835 pval = val;
836 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
837 return make_number (val);
840 case DBUS_TYPE_INT32:
842 dbus_int32_t val;
843 int pval;
844 dbus_message_iter_get_basic (iter, &val);
845 pval = val;
846 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
847 return make_fixnum_or_float (val);
850 case DBUS_TYPE_UINT32:
851 #ifdef DBUS_TYPE_UNIX_FD
852 case DBUS_TYPE_UNIX_FD:
853 #endif
855 dbus_uint32_t val;
856 unsigned int pval;
857 dbus_message_iter_get_basic (iter, &val);
858 pval = val;
859 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
860 return make_fixnum_or_float (val);
863 case DBUS_TYPE_INT64:
865 dbus_int64_t val;
866 printmax_t pval;
867 dbus_message_iter_get_basic (iter, &val);
868 pval = val;
869 XD_DEBUG_MESSAGE ("%c %"pMd, dtype, pval);
870 return make_fixnum_or_float (val);
873 case DBUS_TYPE_UINT64:
875 dbus_uint64_t val;
876 uprintmax_t pval;
877 dbus_message_iter_get_basic (iter, &val);
878 pval = val;
879 XD_DEBUG_MESSAGE ("%c %"pMu, dtype, pval);
880 return make_fixnum_or_float (val);
883 case DBUS_TYPE_DOUBLE:
885 double val;
886 dbus_message_iter_get_basic (iter, &val);
887 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
888 return make_float (val);
891 case DBUS_TYPE_STRING:
892 case DBUS_TYPE_OBJECT_PATH:
893 case DBUS_TYPE_SIGNATURE:
895 char *val;
896 dbus_message_iter_get_basic (iter, &val);
897 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
898 return build_string (val);
901 case DBUS_TYPE_ARRAY:
902 case DBUS_TYPE_VARIANT:
903 case DBUS_TYPE_STRUCT:
904 case DBUS_TYPE_DICT_ENTRY:
906 Lisp_Object result;
907 DBusMessageIter subiter;
908 int subtype;
909 result = Qnil;
910 dbus_message_iter_recurse (iter, &subiter);
911 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
912 != DBUS_TYPE_INVALID)
914 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
915 dbus_message_iter_next (&subiter);
917 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (result));
918 return Fnreverse (result);
921 default:
922 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
923 return Qnil;
927 /* Return the number of references of the shared CONNECTION. */
928 static ptrdiff_t
929 xd_get_connection_references (DBusConnection *connection)
931 ptrdiff_t *refcount;
933 /* We cannot access the DBusConnection structure, it is not public.
934 But we know, that the reference counter is the first field in
935 that structure. */
936 refcount = (void *) &connection;
937 refcount = (void *) *refcount;
938 return *refcount;
941 /* Convert a Lisp D-Bus object to a pointer. */
942 static DBusConnection *
943 xd_lisp_dbus_to_dbus (Lisp_Object bus)
945 return (DBusConnection *) XSAVE_POINTER (bus, 0);
948 /* Return D-Bus connection address. BUS is either a Lisp symbol,
949 :system or :session, or a string denoting the bus address. */
950 static DBusConnection *
951 xd_get_connection_address (Lisp_Object bus)
953 DBusConnection *connection;
954 Lisp_Object val;
956 val = CDR_SAFE (Fassoc (bus, xd_registered_buses, Qnil));
957 if (NILP (val))
958 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
959 else
960 connection = xd_lisp_dbus_to_dbus (val);
962 if (!dbus_connection_get_is_connected (connection))
963 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
965 return connection;
968 /* Return the file descriptor for WATCH, -1 if not found. */
969 static int
970 xd_find_watch_fd (DBusWatch *watch)
972 #if HAVE_DBUS_WATCH_GET_UNIX_FD
973 /* TODO: Reverse these on w32, which prefers the opposite. */
974 int fd = dbus_watch_get_unix_fd (watch);
975 if (fd == -1)
976 fd = dbus_watch_get_socket (watch);
977 #else
978 int fd = dbus_watch_get_fd (watch);
979 #endif
980 return fd;
983 /* Prototype. */
984 static void xd_read_queued_messages (int fd, void *data);
986 /* Start monitoring WATCH for possible I/O. */
987 static dbus_bool_t
988 xd_add_watch (DBusWatch *watch, void *data)
990 unsigned int flags = dbus_watch_get_flags (watch);
991 int fd = xd_find_watch_fd (watch);
993 XD_DEBUG_MESSAGE ("fd %d, write %u, enabled %u",
994 fd, flags & DBUS_WATCH_WRITABLE,
995 dbus_watch_get_enabled (watch));
997 if (fd == -1)
998 return FALSE;
1000 if (dbus_watch_get_enabled (watch))
1002 if (flags & DBUS_WATCH_WRITABLE)
1003 add_write_fd (fd, xd_read_queued_messages, data);
1004 if (flags & DBUS_WATCH_READABLE)
1005 add_read_fd (fd, xd_read_queued_messages, data);
1007 return TRUE;
1010 /* Stop monitoring WATCH for possible I/O.
1011 DATA is the used bus, either a string or QCsystem or QCsession. */
1012 static void
1013 xd_remove_watch (DBusWatch *watch, void *data)
1015 unsigned int flags = dbus_watch_get_flags (watch);
1016 int fd = xd_find_watch_fd (watch);
1018 XD_DEBUG_MESSAGE ("fd %d", fd);
1020 if (fd == -1)
1021 return;
1023 /* Unset session environment. */
1024 #if 0
1025 /* This is buggy, since unsetenv is not thread-safe. */
1026 if (XSYMBOL (QCsession) == data)
1028 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
1029 unsetenv ("DBUS_SESSION_BUS_ADDRESS");
1031 #endif
1033 if (flags & DBUS_WATCH_WRITABLE)
1034 delete_write_fd (fd);
1035 if (flags & DBUS_WATCH_READABLE)
1036 delete_read_fd (fd);
1039 /* Toggle monitoring WATCH for possible I/O. */
1040 static void
1041 xd_toggle_watch (DBusWatch *watch, void *data)
1043 if (dbus_watch_get_enabled (watch))
1044 xd_add_watch (watch, data);
1045 else
1046 xd_remove_watch (watch, data);
1049 /* Close connection to D-Bus BUS. */
1050 static void
1051 xd_close_bus (Lisp_Object bus)
1053 DBusConnection *connection;
1054 Lisp_Object val;
1055 Lisp_Object busobj;
1057 /* Check whether we are connected. */
1058 val = Fassoc (bus, xd_registered_buses, Qnil);
1059 if (NILP (val))
1060 return;
1062 busobj = CDR_SAFE (val);
1063 if (NILP (busobj)) {
1064 xd_registered_buses = Fdelete (val, xd_registered_buses);
1065 return;
1068 /* Retrieve bus address. */
1069 connection = xd_lisp_dbus_to_dbus (busobj);
1071 if (xd_get_connection_references (connection) == 1)
1073 /* Close connection, if there isn't another shared application. */
1074 XD_DEBUG_MESSAGE ("Close connection to bus %s",
1075 XD_OBJECT_TO_STRING (bus));
1076 dbus_connection_close (connection);
1078 xd_registered_buses = Fdelete (val, xd_registered_buses);
1081 else
1082 /* Decrement reference count. */
1083 dbus_connection_unref (connection);
1085 /* Return. */
1086 return;
1089 DEFUN ("dbus--init-bus", Fdbus__init_bus, Sdbus__init_bus, 1, 2, 0,
1090 doc: /* Establish the connection to D-Bus BUS.
1092 This function is dbus internal. You almost certainly want to use
1093 `dbus-init-bus'.
1095 BUS can be either the symbol `:system' or the symbol `:session', or it
1096 can be a string denoting the address of the corresponding bus. For
1097 the system and session buses, this function is called when loading
1098 `dbus.el', there is no need to call it again.
1100 The function returns a number, which counts the connections this Emacs
1101 session has established to the BUS under the same unique name (see
1102 `dbus-get-unique-name'). It depends on the libraries Emacs is linked
1103 with, and on the environment Emacs is running. For example, if Emacs
1104 is linked with the gtk toolkit, and it runs in a GTK-aware environment
1105 like Gnome, another connection might already be established.
1107 When PRIVATE is non-nil, a new connection is established instead of
1108 reusing an existing one. It results in a new unique name at the bus.
1109 This can be used, if it is necessary to distinguish from another
1110 connection used in the same Emacs process, like the one established by
1111 GTK+. It should be used with care for at least the `:system' and
1112 `:session' buses, because other Emacs Lisp packages might already use
1113 this connection to those buses. */)
1114 (Lisp_Object bus, Lisp_Object private)
1116 DBusConnection *connection;
1117 DBusError derror;
1118 Lisp_Object val;
1119 ptrdiff_t refcount;
1121 /* Check parameter. */
1122 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1124 /* Close bus if it is already open. */
1125 xd_close_bus (bus);
1127 /* Check, whether we are still connected. */
1128 val = Fassoc (bus, xd_registered_buses, Qnil);
1129 if (!NILP (val))
1131 connection = xd_get_connection_address (bus);
1132 dbus_connection_ref (connection);
1135 else
1137 /* Initialize. */
1138 dbus_error_init (&derror);
1140 /* Open the connection. */
1141 if (STRINGP (bus))
1142 if (NILP (private))
1143 connection = dbus_connection_open (SSDATA (bus), &derror);
1144 else
1145 connection = dbus_connection_open_private (SSDATA (bus), &derror);
1147 else
1149 DBusBusType bustype = (EQ (bus, QCsystem)
1150 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION);
1151 if (NILP (private))
1152 connection = dbus_bus_get (bustype, &derror);
1153 else
1154 connection = dbus_bus_get_private (bustype, &derror);
1157 if (dbus_error_is_set (&derror))
1158 XD_ERROR (derror);
1160 if (connection == NULL)
1161 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
1163 /* If it is not the system or session bus, we must register
1164 ourselves. Otherwise, we have called dbus_bus_get, which has
1165 configured us to exit if the connection closes - we undo this
1166 setting. */
1167 if (STRINGP (bus))
1168 dbus_bus_register (connection, &derror);
1169 else
1170 dbus_connection_set_exit_on_disconnect (connection, FALSE);
1172 if (dbus_error_is_set (&derror))
1173 XD_ERROR (derror);
1175 /* Add the watch functions. We pass also the bus as data, in
1176 order to distinguish between the buses in xd_remove_watch. */
1177 if (!dbus_connection_set_watch_functions (connection,
1178 xd_add_watch,
1179 xd_remove_watch,
1180 xd_toggle_watch,
1181 SYMBOLP (bus)
1182 ? (void *) XSYMBOL (bus)
1183 : (void *) XSTRING (bus),
1184 NULL))
1185 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
1187 /* Add bus to list of registered buses. */
1188 val = make_save_ptr (connection);
1189 xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses);
1191 /* Cleanup. */
1192 dbus_error_free (&derror);
1195 /* Return reference counter. */
1196 refcount = xd_get_connection_references (connection);
1197 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d",
1198 XD_OBJECT_TO_STRING (bus), refcount);
1199 return make_number (refcount);
1202 DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
1203 1, 1, 0,
1204 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
1205 (Lisp_Object bus)
1207 DBusConnection *connection;
1208 const char *name;
1210 /* Check parameter. */
1211 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1213 /* Retrieve bus address. */
1214 connection = xd_get_connection_address (bus);
1216 /* Request the name. */
1217 name = dbus_bus_get_unique_name (connection);
1218 if (name == NULL)
1219 XD_SIGNAL1 (build_string ("No unique name available"));
1221 /* Return. */
1222 return build_string (name);
1225 DEFUN ("dbus-message-internal", Fdbus_message_internal, Sdbus_message_internal,
1226 4, MANY, 0,
1227 doc: /* Send a D-Bus message.
1228 This is an internal function, it shall not be used outside dbus.el.
1230 The following usages are expected:
1232 `dbus-call-method', `dbus-call-method-asynchronously':
1233 (dbus-message-internal
1234 dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER
1235 &optional :timeout TIMEOUT &rest ARGS)
1237 `dbus-send-signal':
1238 (dbus-message-internal
1239 dbus-message-type-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)
1241 `dbus-method-return-internal':
1242 (dbus-message-internal
1243 dbus-message-type-method-return BUS SERVICE SERIAL &rest ARGS)
1245 `dbus-method-error-internal':
1246 (dbus-message-internal
1247 dbus-message-type-error BUS SERVICE SERIAL &rest ARGS)
1249 usage: (dbus-message-internal &rest REST) */)
1250 (ptrdiff_t nargs, Lisp_Object *args)
1252 Lisp_Object message_type, bus, service, handler;
1253 Lisp_Object path = Qnil;
1254 Lisp_Object interface = Qnil;
1255 Lisp_Object member = Qnil;
1256 Lisp_Object result;
1257 DBusConnection *connection;
1258 DBusMessage *dmessage;
1259 DBusMessageIter iter;
1260 int dtype;
1261 int mtype;
1262 dbus_uint32_t serial = 0;
1263 unsigned int ui_serial;
1264 int timeout = -1;
1265 ptrdiff_t count;
1266 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1268 /* Initialize parameters. */
1269 message_type = args[0];
1270 bus = args[1];
1271 service = args[2];
1272 handler = Qnil;
1274 CHECK_NATNUM (message_type);
1275 if (! (DBUS_MESSAGE_TYPE_INVALID < XFASTINT (message_type)
1276 && XFASTINT (message_type) < DBUS_NUM_MESSAGE_TYPES))
1277 XD_SIGNAL2 (build_string ("Invalid message type"), message_type);
1278 mtype = XFASTINT (message_type);
1280 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1281 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1283 path = args[3];
1284 interface = args[4];
1285 member = args[5];
1286 if (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1287 handler = args[6];
1288 count = (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) ? 7 : 6;
1290 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1292 serial = xd_extract_unsigned (args[3], TYPE_MAXIMUM (dbus_uint32_t));
1293 count = 4;
1296 /* Check parameters. */
1297 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1298 XD_DBUS_VALIDATE_BUS_NAME (service);
1299 if (nargs < count)
1300 xsignal2 (Qwrong_number_of_arguments,
1301 Qdbus_message_internal,
1302 make_number (nargs));
1304 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1305 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1307 XD_DBUS_VALIDATE_PATH (path);
1308 XD_DBUS_VALIDATE_INTERFACE (interface);
1309 XD_DBUS_VALIDATE_MEMBER (member);
1310 if (!NILP (handler) && !FUNCTIONP (handler))
1311 wrong_type_argument (Qinvalid_function, handler);
1314 /* Trace parameters. */
1315 switch (mtype)
1317 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1318 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s %s",
1319 XD_MESSAGE_TYPE_TO_STRING (mtype),
1320 XD_OBJECT_TO_STRING (bus),
1321 XD_OBJECT_TO_STRING (service),
1322 XD_OBJECT_TO_STRING (path),
1323 XD_OBJECT_TO_STRING (interface),
1324 XD_OBJECT_TO_STRING (member),
1325 XD_OBJECT_TO_STRING (handler));
1326 break;
1327 case DBUS_MESSAGE_TYPE_SIGNAL:
1328 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s",
1329 XD_MESSAGE_TYPE_TO_STRING (mtype),
1330 XD_OBJECT_TO_STRING (bus),
1331 XD_OBJECT_TO_STRING (service),
1332 XD_OBJECT_TO_STRING (path),
1333 XD_OBJECT_TO_STRING (interface),
1334 XD_OBJECT_TO_STRING (member));
1335 break;
1336 default: /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1337 ui_serial = serial;
1338 XD_DEBUG_MESSAGE ("%s %s %s %u",
1339 XD_MESSAGE_TYPE_TO_STRING (mtype),
1340 XD_OBJECT_TO_STRING (bus),
1341 XD_OBJECT_TO_STRING (service),
1342 ui_serial);
1345 /* Retrieve bus address. */
1346 connection = xd_get_connection_address (bus);
1348 /* Create the D-Bus message. */
1349 dmessage = dbus_message_new (mtype);
1350 if (dmessage == NULL)
1351 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1353 if (STRINGP (service))
1355 if (mtype != DBUS_MESSAGE_TYPE_SIGNAL)
1356 /* Set destination. */
1358 if (!dbus_message_set_destination (dmessage, SSDATA (service)))
1359 XD_SIGNAL2 (build_string ("Unable to set the destination"),
1360 service);
1363 else
1364 /* Set destination for unicast signals. */
1366 Lisp_Object uname;
1368 /* If it is the same unique name as we are registered at the
1369 bus or an unknown name, we regard it as broadcast message
1370 due to backward compatibility. */
1371 if (dbus_bus_name_has_owner (connection, SSDATA (service), NULL))
1372 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1373 else
1374 uname = Qnil;
1376 if (STRINGP (uname)
1377 && (strcmp (dbus_bus_get_unique_name (connection), SSDATA (uname))
1378 != 0)
1379 && (!dbus_message_set_destination (dmessage, SSDATA (service))))
1380 XD_SIGNAL2 (build_string ("Unable to set signal destination"),
1381 service);
1385 /* Set message parameters. */
1386 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1387 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1389 if ((!dbus_message_set_path (dmessage, SSDATA (path)))
1390 || (!dbus_message_set_interface (dmessage, SSDATA (interface)))
1391 || (!dbus_message_set_member (dmessage, SSDATA (member))))
1392 XD_SIGNAL1 (build_string ("Unable to set the message parameter"));
1395 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1397 if (!dbus_message_set_reply_serial (dmessage, serial))
1398 XD_SIGNAL1 (build_string ("Unable to create a return message"));
1400 if ((mtype == DBUS_MESSAGE_TYPE_ERROR)
1401 && (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED)))
1402 XD_SIGNAL1 (build_string ("Unable to create an error message"));
1405 /* Check for timeout parameter. */
1406 if ((count + 2 <= nargs) && EQ (args[count], QCtimeout))
1408 CHECK_NATNUM (args[count+1]);
1409 timeout = min (XFASTINT (args[count+1]), INT_MAX);
1410 count = count+2;
1413 /* Initialize parameter list of message. */
1414 dbus_message_iter_init_append (dmessage, &iter);
1416 /* Append parameters to the message. */
1417 for (; count < nargs; ++count)
1419 dtype = XD_OBJECT_TO_DBUS_TYPE (args[count]);
1420 if (count + 1 < nargs && XD_DBUS_TYPE_P (args[count]))
1422 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1423 XD_DEBUG_VALID_LISP_OBJECT_P (args[count+1]);
1424 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", count - 4,
1425 XD_OBJECT_TO_STRING (args[count]),
1426 XD_OBJECT_TO_STRING (args[count+1]));
1427 ++count;
1429 else
1431 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1432 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", count - 4,
1433 XD_OBJECT_TO_STRING (args[count]));
1436 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1437 indication that there is no parent type. */
1438 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[count]);
1440 xd_append_arg (dtype, args[count], &iter);
1443 if (!NILP (handler))
1445 /* Send the message. The message is just added to the outgoing
1446 message queue. */
1447 if (!dbus_connection_send_with_reply (connection, dmessage,
1448 NULL, timeout))
1449 XD_SIGNAL1 (build_string ("Cannot send message"));
1451 /* The result is the key in Vdbus_registered_objects_table. */
1452 serial = dbus_message_get_serial (dmessage);
1453 result = list3 (QCserial, bus, make_fixnum_or_float (serial));
1455 /* Create a hash table entry. */
1456 Fputhash (result, handler, Vdbus_registered_objects_table);
1458 else
1460 /* Send the message. The message is just added to the outgoing
1461 message queue. */
1462 if (!dbus_connection_send (connection, dmessage, NULL))
1463 XD_SIGNAL1 (build_string ("Cannot send message"));
1465 result = Qnil;
1468 XD_DEBUG_MESSAGE ("Message sent: %s", XD_OBJECT_TO_STRING (result));
1470 /* Cleanup. */
1471 dbus_message_unref (dmessage);
1473 /* Return the result. */
1474 return result;
1477 /* Read one queued incoming message of the D-Bus BUS.
1478 BUS is either a Lisp symbol, :system or :session, or a string denoting
1479 the bus address. */
1480 static void
1481 xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
1483 Lisp_Object args, key, value;
1484 struct input_event event;
1485 DBusMessage *dmessage;
1486 DBusMessageIter iter;
1487 int dtype;
1488 int mtype;
1489 dbus_uint32_t serial;
1490 unsigned int ui_serial;
1491 const char *uname, *path, *interface, *member;
1493 dmessage = dbus_connection_pop_message (connection);
1495 /* Return if there is no queued message. */
1496 if (dmessage == NULL)
1497 return;
1499 /* Collect the parameters. */
1500 args = Qnil;
1502 /* Loop over the resulting parameters. Construct a list. */
1503 if (dbus_message_iter_init (dmessage, &iter))
1505 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1506 != DBUS_TYPE_INVALID)
1508 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1509 dbus_message_iter_next (&iter);
1511 /* The arguments are stored in reverse order. Reorder them. */
1512 args = Fnreverse (args);
1515 /* Read message type, message serial, unique name, object path,
1516 interface and member from the message. */
1517 mtype = dbus_message_get_type (dmessage);
1518 ui_serial = serial =
1519 ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1520 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1521 ? dbus_message_get_reply_serial (dmessage)
1522 : dbus_message_get_serial (dmessage);
1523 uname = dbus_message_get_sender (dmessage);
1524 path = dbus_message_get_path (dmessage);
1525 interface = dbus_message_get_interface (dmessage);
1526 member = dbus_message_get_member (dmessage);
1528 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
1529 XD_MESSAGE_TYPE_TO_STRING (mtype),
1530 ui_serial, uname, path, interface, member,
1531 XD_OBJECT_TO_STRING (args));
1533 if (mtype == DBUS_MESSAGE_TYPE_INVALID)
1534 goto cleanup;
1536 else if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1537 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1539 /* Search for a registered function of the message. */
1540 key = list3 (QCserial, bus, make_fixnum_or_float (serial));
1541 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
1543 /* There shall be exactly one entry. Construct an event. */
1544 if (NILP (value))
1545 goto cleanup;
1547 /* Remove the entry. */
1548 Fremhash (key, Vdbus_registered_objects_table);
1550 /* Construct an event. */
1551 EVENT_INIT (event);
1552 event.kind = DBUS_EVENT;
1553 event.frame_or_window = Qnil;
1554 event.arg = Fcons (value, args);
1557 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
1559 /* Vdbus_registered_objects_table requires non-nil interface and
1560 member. */
1561 if ((interface == NULL) || (member == NULL))
1562 goto cleanup;
1564 /* Search for a registered function of the message. */
1565 key = list4 (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL ? QCmethod : QCsignal,
1566 bus, build_string (interface), build_string (member));
1567 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
1569 /* Loop over the registered functions. Construct an event. */
1570 while (!NILP (value))
1572 key = CAR_SAFE (value);
1573 /* key has the structure (UNAME SERVICE PATH HANDLER). */
1574 if (((uname == NULL)
1575 || (NILP (CAR_SAFE (key)))
1576 || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0))
1577 && ((path == NULL)
1578 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1579 || (strcmp (path,
1580 SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1581 == 0))
1582 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
1584 EVENT_INIT (event);
1585 event.kind = DBUS_EVENT;
1586 event.frame_or_window = Qnil;
1587 event.arg
1588 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
1589 break;
1591 value = CDR_SAFE (value);
1594 if (NILP (value))
1595 goto cleanup;
1598 /* Add type, serial, uname, path, interface and member to the event. */
1599 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1600 event.arg);
1601 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1602 event.arg);
1603 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1604 event.arg);
1605 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1606 event.arg);
1607 event.arg = Fcons (make_fixnum_or_float (serial), event.arg);
1608 event.arg = Fcons (make_number (mtype), event.arg);
1610 /* Add the bus symbol to the event. */
1611 event.arg = Fcons (bus, event.arg);
1613 /* Store it into the input event queue. */
1614 kbd_buffer_store_event (&event);
1616 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
1618 /* Cleanup. */
1619 cleanup:
1620 dbus_message_unref (dmessage);
1623 /* Read queued incoming messages of the D-Bus BUS.
1624 BUS is either a Lisp symbol, :system or :session, or a string denoting
1625 the bus address. */
1626 static Lisp_Object
1627 xd_read_message (Lisp_Object bus)
1629 /* Retrieve bus address. */
1630 DBusConnection *connection = xd_get_connection_address (bus);
1632 /* Non blocking read of the next available message. */
1633 dbus_connection_read_write (connection, 0);
1635 while (dbus_connection_get_dispatch_status (connection)
1636 != DBUS_DISPATCH_COMPLETE)
1637 xd_read_message_1 (connection, bus);
1638 return Qnil;
1641 /* Callback called when something is ready to read or write. */
1642 static void
1643 xd_read_queued_messages (int fd, void *data)
1645 Lisp_Object busp = xd_registered_buses;
1646 Lisp_Object bus = Qnil;
1647 Lisp_Object key;
1649 /* Find bus related to fd. */
1650 if (data != NULL)
1651 while (!NILP (busp))
1653 key = CAR_SAFE (CAR_SAFE (busp));
1654 if ((SYMBOLP (key) && XSYMBOL (key) == data)
1655 || (STRINGP (key) && XSTRING (key) == data))
1656 bus = key;
1657 busp = CDR_SAFE (busp);
1660 if (NILP (bus))
1661 return;
1663 /* We ignore all Lisp errors during the call. */
1664 xd_in_read_queued_messages = 1;
1665 internal_catch (Qdbus_error, xd_read_message, bus);
1666 xd_in_read_queued_messages = 0;
1670 void
1671 init_dbusbind (void)
1673 /* We do not want to abort. */
1674 xputenv ("DBUS_FATAL_WARNINGS=0");
1677 void
1678 syms_of_dbusbind (void)
1680 defsubr (&Sdbus__init_bus);
1681 defsubr (&Sdbus_get_unique_name);
1683 DEFSYM (Qdbus_message_internal, "dbus-message-internal");
1684 defsubr (&Sdbus_message_internal);
1686 /* D-Bus error symbol. */
1687 DEFSYM (Qdbus_error, "dbus-error");
1688 Fput (Qdbus_error, Qerror_conditions,
1689 list2 (Qdbus_error, Qerror));
1690 Fput (Qdbus_error, Qerror_message,
1691 build_pure_c_string ("D-Bus error"));
1693 /* Lisp symbols of the system and session buses. */
1694 DEFSYM (QCsystem, ":system");
1695 DEFSYM (QCsession, ":session");
1697 /* Lisp symbol for method call timeout. */
1698 DEFSYM (QCtimeout, ":timeout");
1700 /* Lisp symbols of D-Bus types. */
1701 DEFSYM (QCbyte, ":byte");
1702 DEFSYM (QCboolean, ":boolean");
1703 DEFSYM (QCint16, ":int16");
1704 DEFSYM (QCuint16, ":uint16");
1705 DEFSYM (QCint32, ":int32");
1706 DEFSYM (QCuint32, ":uint32");
1707 DEFSYM (QCint64, ":int64");
1708 DEFSYM (QCuint64, ":uint64");
1709 DEFSYM (QCdouble, ":double");
1710 DEFSYM (QCstring, ":string");
1711 DEFSYM (QCobject_path, ":object-path");
1712 DEFSYM (QCsignature, ":signature");
1713 #ifdef DBUS_TYPE_UNIX_FD
1714 DEFSYM (QCunix_fd, ":unix-fd");
1715 #endif
1716 DEFSYM (QCarray, ":array");
1717 DEFSYM (QCvariant, ":variant");
1718 DEFSYM (QCstruct, ":struct");
1719 DEFSYM (QCdict_entry, ":dict-entry");
1721 /* Lisp symbols of objects in `dbus-registered-objects-table'. */
1722 DEFSYM (QCserial, ":serial");
1723 DEFSYM (QCmethod, ":method");
1724 DEFSYM (QCsignal, ":signal");
1726 DEFVAR_LISP ("dbus-compiled-version",
1727 Vdbus_compiled_version,
1728 doc: /* The version of D-Bus Emacs is compiled against. */);
1729 #ifdef DBUS_VERSION_STRING
1730 Vdbus_compiled_version = build_pure_c_string (DBUS_VERSION_STRING);
1731 #else
1732 Vdbus_compiled_version = Qnil;
1733 #endif
1735 DEFVAR_LISP ("dbus-runtime-version",
1736 Vdbus_runtime_version,
1737 doc: /* The version of D-Bus Emacs runs with. */);
1739 #ifdef DBUS_VERSION
1740 int major, minor, micro;
1741 char s[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
1742 dbus_get_version (&major, &minor, &micro);
1743 Vdbus_runtime_version
1744 = make_formatted_string (s, "%d.%d.%d", major, minor, micro);
1745 #else
1746 Vdbus_runtime_version = Qnil;
1747 #endif
1750 DEFVAR_LISP ("dbus-message-type-invalid",
1751 Vdbus_message_type_invalid,
1752 doc: /* This value is never a valid message type. */);
1753 Vdbus_message_type_invalid = make_number (DBUS_MESSAGE_TYPE_INVALID);
1755 DEFVAR_LISP ("dbus-message-type-method-call",
1756 Vdbus_message_type_method_call,
1757 doc: /* Message type of a method call message. */);
1758 Vdbus_message_type_method_call = make_number (DBUS_MESSAGE_TYPE_METHOD_CALL);
1760 DEFVAR_LISP ("dbus-message-type-method-return",
1761 Vdbus_message_type_method_return,
1762 doc: /* Message type of a method return message. */);
1763 Vdbus_message_type_method_return
1764 = make_number (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1766 DEFVAR_LISP ("dbus-message-type-error",
1767 Vdbus_message_type_error,
1768 doc: /* Message type of an error reply message. */);
1769 Vdbus_message_type_error = make_number (DBUS_MESSAGE_TYPE_ERROR);
1771 DEFVAR_LISP ("dbus-message-type-signal",
1772 Vdbus_message_type_signal,
1773 doc: /* Message type of a signal message. */);
1774 Vdbus_message_type_signal = make_number (DBUS_MESSAGE_TYPE_SIGNAL);
1776 DEFVAR_LISP ("dbus-registered-objects-table",
1777 Vdbus_registered_objects_table,
1778 doc: /* Hash table of registered functions for D-Bus.
1780 There are two different uses of the hash table: for accessing
1781 registered interfaces properties, targeted by signals or method calls,
1782 and for calling handlers in case of non-blocking method call returns.
1784 In the first case, the key in the hash table is the list (TYPE BUS
1785 INTERFACE MEMBER). TYPE is one of the Lisp symbols `:method',
1786 `:signal' or `:property'. BUS is either a Lisp symbol, `:system' or
1787 `:session', or a string denoting the bus address. INTERFACE is a
1788 string which denotes a D-Bus interface, and MEMBER, also a string, is
1789 either a method, a signal or a property INTERFACE is offering. All
1790 arguments but BUS must not be nil.
1792 The value in the hash table is a list of quadruple lists ((UNAME
1793 SERVICE PATH OBJECT [RULE]) ...). SERVICE is the service name as
1794 registered, UNAME is the corresponding unique name. In case of
1795 registered methods and properties, UNAME is nil. PATH is the object
1796 path of the sending object. All of them can be nil, which means a
1797 wildcard then. OBJECT is either the handler to be called when a D-Bus
1798 message, which matches the key criteria, arrives (TYPE `:method' and
1799 `:signal'), or a cons cell containing the value of the property (TYPE
1800 `:property').
1802 For entries of type `:signal', there is also a fifth element RULE,
1803 which keeps the match string the signal is registered with.
1805 In the second case, the key in the hash table is the list (:serial BUS
1806 SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
1807 string denoting the bus address. SERIAL is the serial number of the
1808 non-blocking method call, a reply is expected. Both arguments must
1809 not be nil. The value in the hash table is HANDLER, the function to
1810 be called when the D-Bus reply message arrives. */);
1811 Vdbus_registered_objects_table = CALLN (Fmake_hash_table, QCtest, Qequal);
1813 DEFVAR_LISP ("dbus-debug", Vdbus_debug,
1814 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
1815 #ifdef DBUS_DEBUG
1816 Vdbus_debug = Qt;
1817 /* We can also set environment variable DBUS_VERBOSE=1 in order to
1818 see more traces. This requires libdbus-1 to be configured with
1819 --enable-verbose-mode. */
1820 #else
1821 Vdbus_debug = Qnil;
1822 #endif
1824 /* Initialize internal objects. */
1825 xd_registered_buses = Qnil;
1826 staticpro (&xd_registered_buses);
1828 Fprovide (intern_c_string ("dbusbind"), Qnil);
1832 #endif /* HAVE_DBUS */