Merge changes from emacs-24 branch
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2 1/* Elisp bindings for D-Bus.
acaf905b 2 Copyright (C) 2007-2012 Free Software Foundation, Inc.
033b73e2
MA
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
033b73e2 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
033b73e2
MA
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
033b73e2 18
08a494a3 19#include <config.h>
033b73e2
MA
20
21#ifdef HAVE_DBUS
f5306ca3 22#include <stdio.h>
033b73e2 23#include <dbus/dbus.h>
d7306fe6 24#include <setjmp.h>
033b73e2
MA
25#include "lisp.h"
26#include "frame.h"
27#include "termhooks.h"
28#include "keyboard.h"
3fad2ad2 29#include "process.h"
033b73e2 30
dcbf5805
MA
31#ifndef DBUS_NUM_MESSAGE_TYPES
32#define DBUS_NUM_MESSAGE_TYPES 5
33#endif
34
033b73e2
MA
35\f
36/* Subroutines. */
955cbe7b 37static Lisp_Object Qdbus_init_bus;
955cbe7b 38static Lisp_Object Qdbus_get_unique_name;
dcbf5805 39static Lisp_Object Qdbus_message_internal;
033b73e2
MA
40
41/* D-Bus error symbol. */
955cbe7b 42static Lisp_Object Qdbus_error;
033b73e2
MA
43
44/* Lisp symbols of the system and session buses. */
955cbe7b 45static Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 46
90b3fc84 47/* Lisp symbol for method call timeout. */
955cbe7b 48static Lisp_Object QCdbus_timeout;
90b3fc84 49
54371585 50/* Lisp symbols of D-Bus types. */
955cbe7b
PE
51static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
52static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
53static Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
54static Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
55static Lisp_Object QCdbus_type_double, QCdbus_type_string;
56static Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
da1fec2b 57#ifdef DBUS_TYPE_UNIX_FD
b4289b64 58static Lisp_Object QCdbus_type_unix_fd;
da1fec2b 59#endif
955cbe7b
PE
60static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
61static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
54371585 62
dcbf5805
MA
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
1dae9197 67/* Whether we are reading a D-Bus event. */
16390cd2 68static int xd_in_read_queued_messages = 0;
1dae9197 69
033b73e2
MA
70\f
71/* We use "xd_" and "XD_" as prefix for all internal symbols, because
72 we don't want to poison other namespaces with "dbus_". */
73
1dae9197
MA
74/* Raise a signal. If we are reading events, we cannot signal; we
75 throw to xd_read_queued_messages then. */
76#define XD_SIGNAL1(arg) \
77 do { \
78 if (xd_in_read_queued_messages) \
79 Fthrow (Qdbus_error, Qnil); \
80 else \
81 xsignal1 (Qdbus_error, arg); \
82 } while (0)
83
84#define XD_SIGNAL2(arg1, arg2) \
85 do { \
86 if (xd_in_read_queued_messages) \
87 Fthrow (Qdbus_error, Qnil); \
88 else \
89 xsignal2 (Qdbus_error, arg1, arg2); \
90 } while (0)
91
92#define XD_SIGNAL3(arg1, arg2, arg3) \
93 do { \
94 if (xd_in_read_queued_messages) \
95 Fthrow (Qdbus_error, Qnil); \
96 else \
97 xsignal3 (Qdbus_error, arg1, arg2, arg3); \
98 } while (0)
99
54371585 100/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 101#define XD_ERROR(error) \
17bc8f94 102 do { \
033b73e2 103 /* Remove the trailing newline. */ \
573f4b54
PE
104 char const *mess = error.message; \
105 char const *nl = strchr (mess, '\n'); \
106 Lisp_Object err = make_string (mess, nl ? nl - mess : strlen (mess)); \
107 dbus_error_free (&error); \
108 XD_SIGNAL1 (err); \
17bc8f94 109 } while (0)
033b73e2
MA
110
111/* Macros for debugging. In order to enable them, build with
dcbf5805 112 "env MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
033b73e2 113#ifdef DBUS_DEBUG
dcbf5805
MA
114#define XD_DEBUG_MESSAGE(...) \
115 do { \
116 char s[1024]; \
573f4b54 117 snprintf (s, sizeof s, __VA_ARGS__); \
dcbf5805
MA
118 printf ("%s: %s\n", __func__, s); \
119 message ("%s: %s", __func__, s); \
17bc8f94 120 } while (0)
033b73e2 121#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
122 do { \
123 if (!valid_lisp_object_p (object)) \
124 { \
125 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
1dae9197 126 XD_SIGNAL1 (build_string ("Assertion failure")); \
17bc8f94
MA
127 } \
128 } while (0)
033b73e2
MA
129
130#else /* !DBUS_DEBUG */
17bc8f94
MA
131#define XD_DEBUG_MESSAGE(...) \
132 do { \
133 if (!NILP (Vdbus_debug)) \
134 { \
135 char s[1024]; \
dcbf5805 136 snprintf (s, sizeof s, __VA_ARGS__); \
17bc8f94 137 message ("%s: %s", __func__, s); \
80f9d13b 138 } \
17bc8f94 139 } while (0)
033b73e2
MA
140#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
141#endif
142
87cf1a39 143/* Check whether TYPE is a basic DBusType. */
da1fec2b
MA
144#ifdef DBUS_TYPE_UNIX_FD
145#define XD_BASIC_DBUS_TYPE(type) \
146 ((type == DBUS_TYPE_BYTE) \
147 || (type == DBUS_TYPE_BOOLEAN) \
148 || (type == DBUS_TYPE_INT16) \
149 || (type == DBUS_TYPE_UINT16) \
150 || (type == DBUS_TYPE_INT32) \
151 || (type == DBUS_TYPE_UINT32) \
152 || (type == DBUS_TYPE_INT64) \
153 || (type == DBUS_TYPE_UINT64) \
154 || (type == DBUS_TYPE_DOUBLE) \
155 || (type == DBUS_TYPE_STRING) \
156 || (type == DBUS_TYPE_OBJECT_PATH) \
01768686 157 || (type == DBUS_TYPE_SIGNATURE) \
da1fec2b
MA
158 || (type == DBUS_TYPE_UNIX_FD))
159#else
87cf1a39
MA
160#define XD_BASIC_DBUS_TYPE(type) \
161 ((type == DBUS_TYPE_BYTE) \
162 || (type == DBUS_TYPE_BOOLEAN) \
163 || (type == DBUS_TYPE_INT16) \
164 || (type == DBUS_TYPE_UINT16) \
165 || (type == DBUS_TYPE_INT32) \
166 || (type == DBUS_TYPE_UINT32) \
167 || (type == DBUS_TYPE_INT64) \
168 || (type == DBUS_TYPE_UINT64) \
169 || (type == DBUS_TYPE_DOUBLE) \
170 || (type == DBUS_TYPE_STRING) \
171 || (type == DBUS_TYPE_OBJECT_PATH) \
172 || (type == DBUS_TYPE_SIGNATURE))
da1fec2b 173#endif
87cf1a39 174
78c38319 175/* This was a macro. On Solaris 2.11 it was said to compile for
e1dbe924 176 hours, when optimization is enabled. So we have transferred it into
78c38319 177 a function. */
54371585
MA
178/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
179 of the predefined D-Bus type symbols. */
78c38319 180static int
971de7fb 181xd_symbol_to_dbus_type (Lisp_Object object)
78c38319
MA
182{
183 return
184 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
185 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN
186 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16
187 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16
188 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32
189 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32
190 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64
191 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64
192 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE
193 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING
194 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH
195 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE
da1fec2b
MA
196#ifdef DBUS_TYPE_UNIX_FD
197 : (EQ (object, QCdbus_type_unix_fd)) ? DBUS_TYPE_UNIX_FD
198#endif
78c38319
MA
199 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
200 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
201 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
202 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY
203 : DBUS_TYPE_INVALID);
204}
87cf1a39
MA
205
206/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
207#define XD_DBUS_TYPE_P(object) \
78c38319 208 (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
54371585
MA
209
210/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
211 convert Lisp objects, being arguments of `dbus-call-method' or
212 `dbus-send-signal', into corresponding C values appended as
213 arguments to a D-Bus message. */
87cf1a39
MA
214#define XD_OBJECT_TO_DBUS_TYPE(object) \
215 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
216 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
217 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
218 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
219 : (STRINGP (object)) ? DBUS_TYPE_STRING \
78c38319 220 : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
07a4cb03
MA
221 : (CONSP (object)) \
222 ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
78c38319 223 ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
07a4cb03 224 ? DBUS_TYPE_ARRAY \
78c38319 225 : xd_symbol_to_dbus_type (CAR_SAFE (object))) \
07a4cb03 226 : DBUS_TYPE_ARRAY) \
87cf1a39
MA
227 : DBUS_TYPE_INVALID)
228
229/* Return a list pointer which does not have a Lisp symbol as car. */
a8e72f4f 230#define XD_NEXT_VALUE(object) \
5125905e 231 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
87cf1a39 232
dcbf5805
MA
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
08686060
PE
251/* Check whether X is a valid dbus serial number. If valid, set
252 SERIAL to its value. Otherwise, signal an error. */
dcbf5805
MA
253#define XD_CHECK_DBUS_SERIAL(x, serial) \
254 do { \
255 dbus_uint32_t DBUS_SERIAL_MAX = -1; \
256 if (NATNUMP (x) && XINT (x) <= DBUS_SERIAL_MAX) \
257 serial = XINT (x); \
258 else if (MOST_POSITIVE_FIXNUM < DBUS_SERIAL_MAX \
259 && FLOATP (x) \
260 && 0 <= XFLOAT_DATA (x) \
261 && XFLOAT_DATA (x) <= DBUS_SERIAL_MAX) \
262 serial = XFLOAT_DATA (x); \
263 else \
264 XD_SIGNAL2 (build_string ("Invalid dbus serial"), x); \
265 } while (0)
266
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
de85e130
PE
294#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
295 || XD_DBUS_VALIDATE_OBJECT || HAVE_DBUS_VALIDATE_MEMBER)
dcbf5805
MA
296#define XD_DBUS_VALIDATE_OBJECT(object, func) \
297 do { \
298 if (!NILP (object)) \
299 { \
300 DBusError derror; \
301 CHECK_STRING (object); \
302 dbus_error_init (&derror); \
303 if (!func (SSDATA (object), &derror)) \
304 XD_ERROR (derror); \
305 /* Cleanup. */ \
306 dbus_error_free (&derror); \
307 } \
308 } while (0)
de85e130 309#endif
dcbf5805
MA
310
311#if HAVE_DBUS_VALIDATE_BUS_NAME
312#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
313 XD_DBUS_VALIDATE_OBJECT(bus_name, dbus_validate_bus_name);
314#else
315#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
316 if (!NILP (bus_name)) CHECK_STRING (bus_name);
317#endif
318
319#if HAVE_DBUS_VALIDATE_PATH
320#define XD_DBUS_VALIDATE_PATH(path) \
321 XD_DBUS_VALIDATE_OBJECT(path, dbus_validate_path);
322#else
323#define XD_DBUS_VALIDATE_PATH(path) \
324 if (!NILP (path)) CHECK_STRING (path);
325#endif
326
327#if HAVE_DBUS_VALIDATE_INTERFACE
328#define XD_DBUS_VALIDATE_INTERFACE(interface) \
329 XD_DBUS_VALIDATE_OBJECT(interface, dbus_validate_interface);
330#else
331#define XD_DBUS_VALIDATE_INTERFACE(interface) \
332 if (!NILP (interface)) CHECK_STRING (interface);
333#endif
334
335#if HAVE_DBUS_VALIDATE_MEMBER
336#define XD_DBUS_VALIDATE_MEMBER(member) \
337 XD_DBUS_VALIDATE_OBJECT(member, dbus_validate_member);
338#else
339#define XD_DBUS_VALIDATE_MEMBER(member) \
340 if (!NILP (member)) CHECK_STRING (member);
341#endif
08686060 342
e936e76e 343/* Append to SIGNATURE a copy of X, making sure SIGNATURE does
2be7d702
PE
344 not become too long. */
345static void
ecfc0a49 346xd_signature_cat (char *signature, char const *x)
2be7d702
PE
347{
348 ptrdiff_t siglen = strlen (signature);
349 ptrdiff_t xlen = strlen (x);
350 if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
351 string_overflow ();
352 strcat (signature, x);
353}
354
87cf1a39
MA
355/* Compute SIGNATURE of OBJECT. It must have a form that it can be
356 used in dbus_message_iter_open_container. DTYPE is the DBusType
357 the object is related to. It is passed as argument, because it
358 cannot be detected in basic type objects, when they are preceded by
359 a type symbol. PARENT_TYPE is the DBusType of a container this
360 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
361 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
78c38319 362static void
971de7fb 363xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lisp_Object object)
033b73e2 364{
87cf1a39
MA
365 unsigned int subtype;
366 Lisp_Object elt;
2ea16b89 367 char const *subsig;
8666506e 368 int subsiglen;
87cf1a39
MA
369 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
370
371 elt = object;
033b73e2 372
033b73e2
MA
373 switch (dtype)
374 {
54371585
MA
375 case DBUS_TYPE_BYTE:
376 case DBUS_TYPE_UINT16:
54371585 377 CHECK_NATNUM (object);
87cf1a39 378 sprintf (signature, "%c", dtype);
54371585 379 break;
87cf1a39 380
54371585
MA
381 case DBUS_TYPE_BOOLEAN:
382 if (!EQ (object, Qt) && !EQ (object, Qnil))
383 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 384 sprintf (signature, "%c", dtype);
54371585 385 break;
87cf1a39 386
54371585 387 case DBUS_TYPE_INT16:
54371585 388 CHECK_NUMBER (object);
87cf1a39 389 sprintf (signature, "%c", dtype);
54371585 390 break;
87cf1a39 391
dcbf5805
MA
392 case DBUS_TYPE_UINT32:
393 case DBUS_TYPE_UINT64:
394#ifdef DBUS_TYPE_UNIX_FD
395 case DBUS_TYPE_UNIX_FD:
396#endif
397 case DBUS_TYPE_INT32:
398 case DBUS_TYPE_INT64:
033b73e2 399 case DBUS_TYPE_DOUBLE:
dcbf5805 400 CHECK_NUMBER_OR_FLOAT (object);
87cf1a39 401 sprintf (signature, "%c", dtype);
54371585 402 break;
87cf1a39 403
033b73e2 404 case DBUS_TYPE_STRING:
54371585
MA
405 case DBUS_TYPE_OBJECT_PATH:
406 case DBUS_TYPE_SIGNATURE:
407 CHECK_STRING (object);
87cf1a39 408 sprintf (signature, "%c", dtype);
54371585 409 break;
87cf1a39 410
54371585 411 case DBUS_TYPE_ARRAY:
9af5078b 412 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
413 complex element types, we just check the container type, not
414 the whole element's signature. */
54371585 415 CHECK_CONS (object);
87cf1a39 416
5125905e
MA
417 /* Type symbol is optional. */
418 if (EQ (QCdbus_type_array, CAR_SAFE (elt)))
87cf1a39 419 elt = XD_NEXT_VALUE (elt);
5125905e
MA
420
421 /* If the array is empty, DBUS_TYPE_STRING is the default
422 element type. */
423 if (NILP (elt))
424 {
425 subtype = DBUS_TYPE_STRING;
2ea16b89 426 subsig = DBUS_TYPE_STRING_AS_STRING;
5125905e
MA
427 }
428 else
429 {
430 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
431 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
2ea16b89 432 subsig = x;
5125905e
MA
433 }
434
435 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
dcbf5805
MA
436 only element, the value of this element is used as the
437 array's element signature. */
5125905e
MA
438 if ((subtype == DBUS_TYPE_SIGNATURE)
439 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
440 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
2ea16b89 441 subsig = SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39
MA
442
443 while (!NILP (elt))
444 {
5125905e
MA
445 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
446 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
447 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
448 }
449
8666506e
PE
450 subsiglen = snprintf (signature, DBUS_MAXIMUM_SIGNATURE_LENGTH,
451 "%c%s", dtype, subsig);
452 if (! (0 <= subsiglen && subsiglen < DBUS_MAXIMUM_SIGNATURE_LENGTH))
2ea16b89 453 string_overflow ();
54371585 454 break;
87cf1a39 455
54371585 456 case DBUS_TYPE_VARIANT:
9af5078b 457 /* Check that there is exactly one list element. */
54371585 458 CHECK_CONS (object);
87cf1a39
MA
459
460 elt = XD_NEXT_VALUE (elt);
5125905e
MA
461 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
462 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 463
5125905e 464 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 465 wrong_type_argument (intern ("D-Bus"),
5125905e 466 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39 467
a271e124 468 sprintf (signature, "%c", dtype);
54371585 469 break;
87cf1a39 470
54371585 471 case DBUS_TYPE_STRUCT:
9af5078b
MA
472 /* A struct list might contain any number of elements with
473 different types. No further check needed. */
87cf1a39
MA
474 CHECK_CONS (object);
475
476 elt = XD_NEXT_VALUE (elt);
477
478 /* Compose the signature from the elements. It is enclosed by
479 parentheses. */
480 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
481 while (!NILP (elt))
482 {
5125905e
MA
483 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
484 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 485 xd_signature_cat (signature, x);
5125905e 486 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39 487 }
ecfc0a49 488 xd_signature_cat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
54371585 489 break;
54371585 490
87cf1a39 491 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
492 /* Check that there are exactly two list elements, and the first
493 one is of basic type. The dictionary entry itself must be an
494 element of an array. */
87cf1a39 495 CHECK_CONS (object);
54371585 496
9af5078b 497 /* Check the parent object type. */
87cf1a39
MA
498 if (parent_type != DBUS_TYPE_ARRAY)
499 wrong_type_argument (intern ("D-Bus"), object);
54371585 500
87cf1a39
MA
501 /* Compose the signature from the elements. It is enclosed by
502 curly braces. */
503 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 504
87cf1a39
MA
505 /* First element. */
506 elt = XD_NEXT_VALUE (elt);
5125905e
MA
507 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
508 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 509 xd_signature_cat (signature, x);
54371585 510
87cf1a39 511 if (!XD_BASIC_DBUS_TYPE (subtype))
5125905e 512 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
54371585 513
87cf1a39 514 /* Second element. */
5125905e
MA
515 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
516 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
517 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 518 xd_signature_cat (signature, x);
54371585 519
5125905e 520 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 521 wrong_type_argument (intern ("D-Bus"),
5125905e 522 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
54371585 523
87cf1a39 524 /* Closing signature. */
ecfc0a49 525 xd_signature_cat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
87cf1a39 526 break;
54371585 527
87cf1a39
MA
528 default:
529 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
530 }
531
87cf1a39
MA
532 XD_DEBUG_MESSAGE ("%s", signature);
533}
54371585 534
87cf1a39
MA
535/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
536 DTYPE must be a valid DBusType. It is used to convert Lisp
537 objects, being arguments of `dbus-call-method' or
538 `dbus-send-signal', into corresponding C values appended as
539 arguments to a D-Bus message. */
78c38319 540static void
971de7fb 541xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
87cf1a39 542{
87cf1a39
MA
543 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
544 DBusMessageIter subiter;
87cf1a39
MA
545
546 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
547 switch (dtype)
548 {
549 case DBUS_TYPE_BYTE:
2d1fc3c7 550 CHECK_NATNUM (object);
54371585 551 {
2d1fc3c7 552 unsigned char val = XFASTINT (object) & 0xFF;
17bc8f94
MA
553 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
554 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 555 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
556 return;
557 }
87cf1a39 558
17bc8f94
MA
559 case DBUS_TYPE_BOOLEAN:
560 {
561 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
562 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
563 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 564 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
565 return;
566 }
87cf1a39 567
17bc8f94 568 case DBUS_TYPE_INT16:
e454a4a3 569 CHECK_NUMBER (object);
17bc8f94
MA
570 {
571 dbus_int16_t val = XINT (object);
572 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
573 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 574 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
575 return;
576 }
87cf1a39 577
17bc8f94 578 case DBUS_TYPE_UINT16:
2d1fc3c7 579 CHECK_NATNUM (object);
17bc8f94 580 {
2d1fc3c7 581 dbus_uint16_t val = XFASTINT (object);
17bc8f94
MA
582 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
583 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 584 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
585 return;
586 }
87cf1a39 587
17bc8f94
MA
588 case DBUS_TYPE_INT32:
589 {
dcbf5805 590 dbus_int32_t val = extract_float (object);
17bc8f94
MA
591 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
592 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 593 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
594 return;
595 }
87cf1a39 596
17bc8f94 597 case DBUS_TYPE_UINT32:
da1fec2b
MA
598#ifdef DBUS_TYPE_UNIX_FD
599 case DBUS_TYPE_UNIX_FD:
600#endif
17bc8f94 601 {
dcbf5805 602 dbus_uint32_t val = extract_float (object);
17bc8f94
MA
603 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
604 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 605 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
606 return;
607 }
87cf1a39 608
17bc8f94
MA
609 case DBUS_TYPE_INT64:
610 {
dcbf5805 611 dbus_int64_t val = extract_float (object);
17bc8f94
MA
612 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
613 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 614 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
615 return;
616 }
87cf1a39 617
17bc8f94
MA
618 case DBUS_TYPE_UINT64:
619 {
dcbf5805
MA
620 dbus_uint64_t val = extract_float (object);
621 XD_DEBUG_MESSAGE ("%c %"pI"d", dtype, val);
17bc8f94 622 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 623 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94 624 return;
54371585 625 }
87cf1a39 626
17bc8f94 627 case DBUS_TYPE_DOUBLE:
f601cdf3 628 {
dcbf5805 629 double val = extract_float (object);
f601cdf3
KR
630 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
631 if (!dbus_message_iter_append_basic (iter, dtype, &val))
632 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
633 return;
634 }
17bc8f94
MA
635
636 case DBUS_TYPE_STRING:
637 case DBUS_TYPE_OBJECT_PATH:
638 case DBUS_TYPE_SIGNATURE:
e454a4a3 639 CHECK_STRING (object);
17bc8f94 640 {
e454a4a3
SM
641 /* We need to send a valid UTF-8 string. We could encode `object'
642 but by not encoding it, we guarantee it's valid utf-8, even if
643 it contains eight-bit-bytes. Of course, you can still send
644 manually-crafted junk by passing a unibyte string. */
59d6fe83 645 char *val = SSDATA (object);
17bc8f94
MA
646 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
647 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 648 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
649 return;
650 }
651 }
87cf1a39
MA
652
653 else /* Compound types. */
654 {
655
656 /* All compound types except array have a type symbol. For
657 array, it is optional. Skip it. */
5125905e 658 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
87cf1a39
MA
659 object = XD_NEXT_VALUE (object);
660
661 /* Open new subiteration. */
662 switch (dtype)
663 {
664 case DBUS_TYPE_ARRAY:
5125905e
MA
665 /* An array has only elements of the same type. So it is
666 sufficient to check the first element's signature
667 only. */
668
669 if (NILP (object))
670 /* If the array is empty, DBUS_TYPE_STRING is the default
671 element type. */
672 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
673
674 else
675 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
676 the only element, the value of this element is used as
677 the array's element signature. */
678 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
679 == DBUS_TYPE_SIGNATURE)
680 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
681 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
682 {
59d6fe83 683 strcpy (signature, SSDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
5125905e
MA
684 object = CDR_SAFE (XD_NEXT_VALUE (object));
685 }
686
687 else
688 xd_signature (signature,
689 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
690 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
691
692 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
dcbf5805 693 XD_OBJECT_TO_STRING (object));
5125905e
MA
694 if (!dbus_message_iter_open_container (iter, dtype,
695 signature, &subiter))
1dae9197
MA
696 XD_SIGNAL3 (build_string ("Cannot open container"),
697 make_number (dtype), build_string (signature));
5125905e
MA
698 break;
699
87cf1a39 700 case DBUS_TYPE_VARIANT:
5125905e
MA
701 /* A variant has just one element. */
702 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
703 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
704
87cf1a39 705 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
dcbf5805 706 XD_OBJECT_TO_STRING (object));
87cf1a39
MA
707 if (!dbus_message_iter_open_container (iter, dtype,
708 signature, &subiter))
1dae9197
MA
709 XD_SIGNAL3 (build_string ("Cannot open container"),
710 make_number (dtype), build_string (signature));
87cf1a39
MA
711 break;
712
713 case DBUS_TYPE_STRUCT:
714 case DBUS_TYPE_DICT_ENTRY:
9af5078b 715 /* These containers do not require a signature. */
dcbf5805 716 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (object));
87cf1a39 717 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
1dae9197
MA
718 XD_SIGNAL2 (build_string ("Cannot open container"),
719 make_number (dtype));
87cf1a39
MA
720 break;
721 }
722
723 /* Loop over list elements. */
724 while (!NILP (object))
725 {
5125905e 726 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
87cf1a39
MA
727 object = XD_NEXT_VALUE (object);
728
5125905e 729 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
87cf1a39 730
5125905e 731 object = CDR_SAFE (object);
87cf1a39
MA
732 }
733
9af5078b 734 /* Close the subiteration. */
87cf1a39 735 if (!dbus_message_iter_close_container (iter, &subiter))
1dae9197
MA
736 XD_SIGNAL2 (build_string ("Cannot close container"),
737 make_number (dtype));
87cf1a39 738 }
033b73e2
MA
739}
740
741/* Retrieve C value from a DBusMessageIter structure ITER, and return
742 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
743 D-Bus message must be a valid DBusType. Compound D-Bus types
744 result always in a Lisp list. */
78c38319 745static Lisp_Object
971de7fb 746xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
033b73e2
MA
747{
748
749 switch (dtype)
750 {
9af5078b 751 case DBUS_TYPE_BYTE:
9af5078b 752 {
17bc8f94 753 unsigned int val;
9af5078b 754 dbus_message_iter_get_basic (iter, &val);
17bc8f94 755 val = val & 0xFF;
9af5078b
MA
756 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
757 return make_number (val);
758 }
759
033b73e2
MA
760 case DBUS_TYPE_BOOLEAN:
761 {
762 dbus_bool_t val;
763 dbus_message_iter_get_basic (iter, &val);
87cf1a39 764 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
765 return (val == FALSE) ? Qnil : Qt;
766 }
87cf1a39 767
17bc8f94 768 case DBUS_TYPE_INT16:
1cae01f7
AS
769 {
770 dbus_int16_t val;
771 dbus_message_iter_get_basic (iter, &val);
772 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
773 return make_number (val);
774 }
775
17bc8f94
MA
776 case DBUS_TYPE_UINT16:
777 {
778 dbus_uint16_t val;
779 dbus_message_iter_get_basic (iter, &val);
780 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
781 return make_number (val);
782 }
783
033b73e2 784 case DBUS_TYPE_INT32:
1cae01f7
AS
785 {
786 dbus_int32_t val;
787 dbus_message_iter_get_basic (iter, &val);
788 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
789 return make_fixnum_or_float (val);
790 }
791
033b73e2 792 case DBUS_TYPE_UINT32:
da1fec2b
MA
793#ifdef DBUS_TYPE_UNIX_FD
794 case DBUS_TYPE_UNIX_FD:
795#endif
033b73e2
MA
796 {
797 dbus_uint32_t val;
798 dbus_message_iter_get_basic (iter, &val);
17bc8f94 799 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
1cae01f7 800 return make_fixnum_or_float (val);
9af5078b
MA
801 }
802
803 case DBUS_TYPE_INT64:
1cae01f7
AS
804 {
805 dbus_int64_t val;
806 dbus_message_iter_get_basic (iter, &val);
807 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
808 return make_fixnum_or_float (val);
809 }
810
9af5078b
MA
811 case DBUS_TYPE_UINT64:
812 {
813 dbus_uint64_t val;
814 dbus_message_iter_get_basic (iter, &val);
17bc8f94 815 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
9af5078b
MA
816 return make_fixnum_or_float (val);
817 }
818
819 case DBUS_TYPE_DOUBLE:
820 {
821 double val;
822 dbus_message_iter_get_basic (iter, &val);
823 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
824 return make_float (val);
033b73e2 825 }
87cf1a39 826
033b73e2
MA
827 case DBUS_TYPE_STRING:
828 case DBUS_TYPE_OBJECT_PATH:
9af5078b 829 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
830 {
831 char *val;
832 dbus_message_iter_get_basic (iter, &val);
87cf1a39 833 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
834 return build_string (val);
835 }
87cf1a39 836
033b73e2
MA
837 case DBUS_TYPE_ARRAY:
838 case DBUS_TYPE_VARIANT:
839 case DBUS_TYPE_STRUCT:
840 case DBUS_TYPE_DICT_ENTRY:
841 {
842 Lisp_Object result;
843 struct gcpro gcpro1;
033b73e2
MA
844 DBusMessageIter subiter;
845 int subtype;
fa8e045a
MA
846 result = Qnil;
847 GCPRO1 (result);
033b73e2
MA
848 dbus_message_iter_recurse (iter, &subiter);
849 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
850 != DBUS_TYPE_INVALID)
851 {
852 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
853 dbus_message_iter_next (&subiter);
854 }
dcbf5805 855 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (result));
033b73e2
MA
856 RETURN_UNGCPRO (Fnreverse (result));
857 }
87cf1a39 858
033b73e2 859 default:
87cf1a39 860 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
861 return Qnil;
862 }
863}
864
dcbf5805
MA
865/* Return the number of references of the shared CONNECTION. */
866static int
867xd_get_connection_references (DBusConnection *connection)
868{
869 ptrdiff_t *refcount;
de85e130 870
dcbf5805
MA
871 /* We cannot access the DBusConnection structure, it is not public.
872 But we know, that the reference counter is the first field in
873 that structure. */
874 refcount = (void *) &connection;
875 refcount = (void *) *refcount;
876 return *refcount;
877}
878
879/* Return D-Bus connection address. BUS is either a Lisp symbol,
880 :system or :session, or a string denoting the bus address. */
78c38319 881static DBusConnection *
dcbf5805 882xd_get_connection_address (Lisp_Object bus)
033b73e2
MA
883{
884 DBusConnection *connection;
dcbf5805 885 Lisp_Object val;
3f56d3c6 886
dcbf5805
MA
887 val = CDR_SAFE (Fassoc (bus, Vdbus_registered_buses));
888 if (NILP (val))
889 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 890 else
dcbf5805 891 connection = (DBusConnection *) XFASTINT (val);
033b73e2 892
dcbf5805 893 if (!dbus_connection_get_is_connected (connection))
3f56d3c6 894 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 895
033b73e2
MA
896 return connection;
897}
898
3fad2ad2 899/* Return the file descriptor for WATCH, -1 if not found. */
3fad2ad2
J
900static int
901xd_find_watch_fd (DBusWatch *watch)
058ed861 902{
eb4c6ace 903#if HAVE_DBUS_WATCH_GET_UNIX_FD
3fad2ad2
J
904 /* TODO: Reverse these on Win32, which prefers the opposite. */
905 int fd = dbus_watch_get_unix_fd (watch);
906 if (fd == -1)
907 fd = dbus_watch_get_socket (watch);
3f56d3c6 908#else
3fad2ad2 909 int fd = dbus_watch_get_fd (watch);
3f56d3c6 910#endif
3fad2ad2
J
911 return fd;
912}
3f56d3c6 913
08609ffd
MA
914/* Prototype. */
915static void
916xd_read_queued_messages (int fd, void *data, int for_read);
058ed861 917
3fad2ad2 918/* Start monitoring WATCH for possible I/O. */
3fad2ad2
J
919static dbus_bool_t
920xd_add_watch (DBusWatch *watch, void *data)
921{
922 unsigned int flags = dbus_watch_get_flags (watch);
923 int fd = xd_find_watch_fd (watch);
924
925 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
dcbf5805
MA
926 fd, flags & DBUS_WATCH_WRITABLE,
927 dbus_watch_get_enabled (watch));
3fad2ad2
J
928
929 if (fd == -1)
930 return FALSE;
931
932 if (dbus_watch_get_enabled (watch))
933 {
934 if (flags & DBUS_WATCH_WRITABLE)
08609ffd 935 add_write_fd (fd, xd_read_queued_messages, data);
3fad2ad2 936 if (flags & DBUS_WATCH_READABLE)
08609ffd 937 add_read_fd (fd, xd_read_queued_messages, data);
3fad2ad2 938 }
058ed861
MA
939 return TRUE;
940}
941
3fad2ad2
J
942/* Stop monitoring WATCH for possible I/O.
943 DATA is the used bus, either a string or QCdbus_system_bus or
0c372655 944 QCdbus_session_bus. */
3fad2ad2 945static void
971de7fb 946xd_remove_watch (DBusWatch *watch, void *data)
058ed861 947{
3fad2ad2
J
948 unsigned int flags = dbus_watch_get_flags (watch);
949 int fd = xd_find_watch_fd (watch);
3f56d3c6 950
3fad2ad2
J
951 XD_DEBUG_MESSAGE ("fd %d", fd);
952
08609ffd
MA
953 if (fd == -1)
954 return;
777013f2 955
3fad2ad2 956 /* Unset session environment. */
b4289b64 957 if (XSYMBOL (QCdbus_session_bus) == data)
3fad2ad2 958 {
dcbf5805
MA
959 // XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
960 // unsetenv ("DBUS_SESSION_BUS_ADDRESS");
058ed861
MA
961 }
962
3fad2ad2
J
963 if (flags & DBUS_WATCH_WRITABLE)
964 delete_write_fd (fd);
965 if (flags & DBUS_WATCH_READABLE)
966 delete_read_fd (fd);
967}
968
969/* Toggle monitoring WATCH for possible I/O. */
3fad2ad2
J
970static void
971xd_toggle_watch (DBusWatch *watch, void *data)
972{
973 if (dbus_watch_get_enabled (watch))
974 xd_add_watch (watch, data);
975 else
976 xd_remove_watch (watch, data);
058ed861
MA
977}
978
dcbf5805
MA
979/* Close connection to D-Bus BUS. */
980static void
981xd_close_bus (Lisp_Object bus)
982{
983 DBusConnection *connection;
984 Lisp_Object val;
985
986 /* Check whether we are connected. */
987 val = Fassoc (bus, Vdbus_registered_buses);
988 if (NILP (val))
989 return;
990
991 /* Retrieve bus address. */
992 connection = xd_get_connection_address (bus);
993
994 /* Close connection, if there isn't another shared application. */
995 if (xd_get_connection_references (connection) == 1)
996 {
997 XD_DEBUG_MESSAGE ("Close connection to bus %s",
998 XD_OBJECT_TO_STRING (bus));
999 dbus_connection_close (connection);
1000 }
1001
1002 /* Decrement reference count. */
1003 dbus_connection_unref (connection);
1004
1005 /* Remove bus from list of registered buses. */
1006 Vdbus_registered_buses = Fdelete (val, Vdbus_registered_buses);
1007
1008 /* Return. */
1009 return;
1010}
1011
1012DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 2, 0,
1013 doc: /* Establish the connection to D-Bus BUS.
1014
1015BUS can be either the symbol `:system' or the symbol `:session', or it
1016can be a string denoting the address of the corresponding bus. For
1017the system and session buses, this function is called when loading
1018`dbus.el', there is no need to call it again.
1019
1020The function returns a number, which counts the connections this Emacs
1021session has established to the BUS under the same unique name (see
1022`dbus-get-unique-name'). It depends on the libraries Emacs is linked
1023with, and on the environment Emacs is running. For example, if Emacs
1024is linked with the gtk toolkit, and it runs in a GTK-aware environment
1025like Gnome, another connection might already be established.
1026
1027When PRIVATE is non-nil, a new connection is established instead of
1028reusing an existing one. It results in a new unique name at the bus.
1029This can be used, if it is necessary to distinguish from another
1030connection used in the same Emacs process, like the one established by
1031GTK+. It should be used with care for at least the `:system' and
1032`:session' buses, because other Emacs Lisp packages might already use
1033this connection to those buses. */)
1034 (Lisp_Object bus, Lisp_Object private)
058ed861
MA
1035{
1036 DBusConnection *connection;
dcbf5805
MA
1037 DBusError derror;
1038 Lisp_Object val;
1039 int refcount;
058ed861 1040
b4289b64 1041 /* Check parameter. */
dcbf5805
MA
1042 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1043
1044 /* Close bus if it is already open. */
1045 xd_close_bus (bus);
1046
1047 /* Initialize. */
1048 dbus_error_init (&derror);
1049
1050 /* Open the connection. */
1051 if (STRINGP (bus))
1052 if (NILP (private))
1053 connection = dbus_connection_open (SSDATA (bus), &derror);
1054 else
1055 connection = dbus_connection_open_private (SSDATA (bus), &derror);
1056
1057 else
1058 if (NILP (private))
1059 connection = dbus_bus_get (EQ (bus, QCdbus_system_bus)
1060 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1061 &derror);
1062 else
1063 connection = dbus_bus_get_private (EQ (bus, QCdbus_system_bus)
1064 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1065 &derror);
1066
1067 if (dbus_error_is_set (&derror))
1068 XD_ERROR (derror);
1069
1070 if (connection == NULL)
1071 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
1072
1073 /* If it is not the system or session bus, we must register
1074 ourselves. Otherwise, we have called dbus_bus_get, which has
1075 configured us to exit if the connection closes - we undo this
1076 setting. */
1077 if (STRINGP (bus))
1078 dbus_bus_register (connection, &derror);
b4289b64 1079 else
dcbf5805 1080 dbus_connection_set_exit_on_disconnect (connection, FALSE);
371cac43 1081
dcbf5805
MA
1082 if (dbus_error_is_set (&derror))
1083 XD_ERROR (derror);
058ed861 1084
777013f2 1085 /* Add the watch functions. We pass also the bus as data, in order
301b181a 1086 to distinguish between the buses in xd_remove_watch. */
058ed861
MA
1087 if (!dbus_connection_set_watch_functions (connection,
1088 xd_add_watch,
1089 xd_remove_watch,
3fad2ad2 1090 xd_toggle_watch,
dcbf5805
MA
1091 SYMBOLP (bus)
1092 ? (void *) XSYMBOL (bus)
1093 : (void *) XSTRING (bus),
1094 NULL))
058ed861
MA
1095 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
1096
0c372655 1097 /* Add bus to list of registered buses. */
dcbf5805
MA
1098 XSETFASTINT (val, connection);
1099 Vdbus_registered_buses = Fcons (Fcons (bus, val), Vdbus_registered_buses);
0c372655 1100
a79b0f28 1101 /* We do not want to abort. */
78320123 1102 putenv ((char *) "DBUS_FATAL_WARNINGS=0");
a79b0f28 1103
dcbf5805
MA
1104 /* Cleanup. */
1105 dbus_error_free (&derror);
0c372655 1106
dcbf5805
MA
1107 /* Return reference counter. */
1108 refcount = xd_get_connection_references (connection);
1109 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %d",
1110 XD_OBJECT_TO_STRING (bus), refcount);
1111 return make_number (refcount);
058ed861
MA
1112}
1113
033b73e2
MA
1114DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
1115 1, 1, 0,
5125905e 1116 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
5842a27b 1117 (Lisp_Object bus)
033b73e2
MA
1118{
1119 DBusConnection *connection;
48f7d213 1120 const char *name;
033b73e2 1121
dcbf5805
MA
1122 /* Check parameter. */
1123 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1124
1125 /* Retrieve bus address. */
1126 connection = xd_get_connection_address (bus);
033b73e2
MA
1127
1128 /* Request the name. */
48f7d213 1129 name = dbus_bus_get_unique_name (connection);
033b73e2 1130 if (name == NULL)
1dae9197 1131 XD_SIGNAL1 (build_string ("No unique name available"));
033b73e2
MA
1132
1133 /* Return. */
1134 return build_string (name);
1135}
1136
dcbf5805
MA
1137DEFUN ("dbus-message-internal", Fdbus_message_internal, Sdbus_message_internal,
1138 4, MANY, 0,
1139 doc: /* Send a D-Bus message.
1140This is an internal function, it shall not be used outside dbus.el.
1141
1142The following usages are expected:
1143
1144`dbus-call-method', `dbus-call-method-asynchronously':
1145 \(dbus-message-internal
1146 dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER
1147 &optional :timeout TIMEOUT &rest ARGS)
1148
1149`dbus-send-signal':
1150 \(dbus-message-internal
1151 dbus-message-type-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)
1152
1153`dbus-method-return-internal':
1154 \(dbus-message-internal
1155 dbus-message-type-method-return BUS SERVICE SERIAL &rest ARGS)
1156
1157`dbus-method-error-internal':
1158 \(dbus-message-internal
1159 dbus-message-type-error BUS SERVICE SERIAL &rest ARGS)
1160
1161usage: (dbus-message-internal &rest REST) */)
f66c7cf8 1162 (ptrdiff_t nargs, Lisp_Object *args)
033b73e2 1163{
dcbf5805
MA
1164 Lisp_Object message_type, bus, service, handler;
1165 Lisp_Object path = Qnil;
1166 Lisp_Object interface = Qnil;
1167 Lisp_Object member = Qnil;
033b73e2 1168 Lisp_Object result;
dcbf5805 1169 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
033b73e2
MA
1170 DBusConnection *connection;
1171 DBusMessage *dmessage;
033b73e2 1172 DBusMessageIter iter;
eb7c7bf5 1173 unsigned int dtype;
dcbf5805
MA
1174 unsigned int mtype;
1175 dbus_uint32_t serial = 0;
90b3fc84 1176 int timeout = -1;
dcbf5805 1177 ptrdiff_t count;
87cf1a39 1178 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2 1179
dcbf5805
MA
1180 /* Initialize parameters. */
1181 message_type = args[0];
1182 bus = args[1];
1183 service = args[2];
1184 handler = Qnil;
1185
1186 CHECK_NATNUM (message_type);
1187 mtype = XFASTINT (message_type);
1188 if ((mtype <= DBUS_MESSAGE_TYPE_INVALID) || (mtype >= DBUS_NUM_MESSAGE_TYPES))
1189 XD_SIGNAL2 (build_string ("Invalid message type"), message_type);
1190
1191 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1192 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1193 {
1194 path = args[3];
1195 interface = args[4];
1196 member = args[5];
1197 if (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1198 handler = args[6];
1199 count = (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) ? 7 : 6;
1200 }
1201 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1202 {
1203 XD_CHECK_DBUS_SERIAL (args[3], serial);
1204 count = 4;
1205 }
1206
033b73e2 1207 /* Check parameters. */
dcbf5805
MA
1208 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1209 XD_DBUS_VALIDATE_BUS_NAME (service);
1210 if (nargs < count)
1211 xsignal2 (Qwrong_number_of_arguments,
1212 Qdbus_message_internal,
1213 make_number (nargs));
1214
1215 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1216 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1217 {
1218 XD_DBUS_VALIDATE_PATH (path);
1219 XD_DBUS_VALIDATE_INTERFACE (interface);
1220 XD_DBUS_VALIDATE_MEMBER (member);
1221 if (!NILP (handler) && (!FUNCTIONP (handler)))
1222 wrong_type_argument (Qinvalid_function, handler);
1223 }
90b3fc84 1224
dcbf5805
MA
1225 /* Protect Lisp variables. */
1226 GCPRO6 (bus, service, path, interface, member, handler);
1227
1228 /* Trace parameters. */
1229 switch (mtype)
033b73e2 1230 {
dcbf5805
MA
1231 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1232 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s %s",
1233 XD_MESSAGE_TYPE_TO_STRING (mtype),
1234 XD_OBJECT_TO_STRING (bus),
1235 XD_OBJECT_TO_STRING (service),
1236 XD_OBJECT_TO_STRING (path),
1237 XD_OBJECT_TO_STRING (interface),
1238 XD_OBJECT_TO_STRING (member),
1239 XD_OBJECT_TO_STRING (handler));
1240 break;
1241 case DBUS_MESSAGE_TYPE_SIGNAL:
1242 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s",
1243 XD_MESSAGE_TYPE_TO_STRING (mtype),
1244 XD_OBJECT_TO_STRING (bus),
1245 XD_OBJECT_TO_STRING (service),
1246 XD_OBJECT_TO_STRING (path),
1247 XD_OBJECT_TO_STRING (interface),
1248 XD_OBJECT_TO_STRING (member));
1249 break;
1250 default: /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1251 XD_DEBUG_MESSAGE ("%s %s %s %u",
1252 XD_MESSAGE_TYPE_TO_STRING (mtype),
1253 XD_OBJECT_TO_STRING (bus),
1254 XD_OBJECT_TO_STRING (service),
1255 serial);
033b73e2
MA
1256 }
1257
dcbf5805
MA
1258 /* Retrieve bus address. */
1259 connection = xd_get_connection_address (bus);
54371585 1260
dcbf5805
MA
1261 /* Create the D-Bus message. */
1262 dmessage = dbus_message_new (mtype);
1263 if (dmessage == NULL)
1264 {
1265 UNGCPRO;
1266 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1267 }
1268
1269 if (STRINGP (service))
033b73e2 1270 {
dcbf5805
MA
1271 if (mtype != DBUS_MESSAGE_TYPE_SIGNAL)
1272 /* Set destination. */
8c7a4ac5 1273 {
dcbf5805
MA
1274 if (!dbus_message_set_destination (dmessage, SSDATA (service)))
1275 {
1276 UNGCPRO;
1277 XD_SIGNAL2 (build_string ("Unable to set the destination"),
1278 service);
1279 }
8c7a4ac5 1280 }
dcbf5805 1281
8c7a4ac5 1282 else
dcbf5805 1283 /* Set destination for unicast signals. */
8c7a4ac5 1284 {
dcbf5805 1285 Lisp_Object uname;
033b73e2 1286
dcbf5805
MA
1287 /* If it is the same unique name as we are registered at the
1288 bus or an unknown name, we regard it as broadcast message
1289 due to backward compatibility. */
1290 if (dbus_bus_name_has_owner (connection, SSDATA (service), NULL))
1291 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1292 else
1293 uname = Qnil;
87cf1a39 1294
dcbf5805
MA
1295 if (STRINGP (uname)
1296 && (strcmp (dbus_bus_get_unique_name (connection), SSDATA (uname))
1297 != 0)
1298 && (!dbus_message_set_destination (dmessage, SSDATA (service))))
1299 {
1300 UNGCPRO;
1301 XD_SIGNAL2 (build_string ("Unable to set signal destination"),
1302 service);
1303 }
1304 }
033b73e2
MA
1305 }
1306
dcbf5805
MA
1307 /* Set message parameters. */
1308 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1309 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
033b73e2 1310 {
dcbf5805
MA
1311 if ((!dbus_message_set_path (dmessage, SSDATA (path)))
1312 || (!dbus_message_set_interface (dmessage, SSDATA (interface)))
1313 || (!dbus_message_set_member (dmessage, SSDATA (member))))
2c3a8b27 1314 {
dcbf5805
MA
1315 UNGCPRO;
1316 XD_SIGNAL1 (build_string ("Unable to set the message parameter"));
2c3a8b27 1317 }
033b73e2 1318 }
13ecc6dc 1319
dcbf5805
MA
1320 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1321 {
1322 if (!dbus_message_set_reply_serial (dmessage, serial))
1323 {
1324 UNGCPRO;
1325 XD_SIGNAL1 (build_string ("Unable to create a return message"));
1326 }
13ecc6dc 1327
dcbf5805
MA
1328 if ((mtype == DBUS_MESSAGE_TYPE_ERROR)
1329 && (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED)))
1330 {
1331 UNGCPRO;
1332 XD_SIGNAL1 (build_string ("Unable to create a error message"));
1333 }
1334 }
13ecc6dc
MA
1335
1336 /* Check for timeout parameter. */
dcbf5805 1337 if ((count+2 <= nargs) && (EQ ((args[count]), QCdbus_timeout)))
13ecc6dc 1338 {
dcbf5805
MA
1339 CHECK_NATNUM (args[count+1]);
1340 timeout = XFASTINT (args[count+1]);
1341 count = count+2;
13ecc6dc
MA
1342 }
1343
1344 /* Initialize parameter list of message. */
1345 dbus_message_iter_init_append (dmessage, &iter);
1346
1347 /* Append parameters to the message. */
dcbf5805 1348 for (; count < nargs; ++count)
13ecc6dc 1349 {
dcbf5805
MA
1350 dtype = XD_OBJECT_TO_DBUS_TYPE (args[count]);
1351 if (XD_DBUS_TYPE_P (args[count]))
13ecc6dc 1352 {
dcbf5805
MA
1353 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1354 XD_DEBUG_VALID_LISP_OBJECT_P (args[count+1]);
1355 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", count - 4,
1356 XD_OBJECT_TO_STRING (args[count]),
1357 XD_OBJECT_TO_STRING (args[count+1]));
1358 ++count;
13ecc6dc
MA
1359 }
1360 else
1361 {
dcbf5805
MA
1362 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1363 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", count - 4,
1364 XD_OBJECT_TO_STRING (args[count]));
13ecc6dc
MA
1365 }
1366
1367 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1368 indication that there is no parent type. */
dcbf5805 1369 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[count]);
13ecc6dc 1370
dcbf5805 1371 xd_append_arg (dtype, args[count], &iter);
13ecc6dc
MA
1372 }
1373
ca4f31ea
MA
1374 if (!NILP (handler))
1375 {
1376 /* Send the message. The message is just added to the outgoing
1377 message queue. */
1378 if (!dbus_connection_send_with_reply (connection, dmessage,
1379 NULL, timeout))
dcbf5805
MA
1380 {
1381 UNGCPRO;
1382 XD_SIGNAL1 (build_string ("Cannot send message"));
1383 }
1384
f04bb9b2 1385 /* The result is the key in Vdbus_registered_objects_table. */
08686060 1386 serial = dbus_message_get_serial (dmessage);
dcbf5805
MA
1387 result = list3 (QCdbus_registered_serial,
1388 bus, make_fixnum_or_float (serial));
13ecc6dc 1389
ca4f31ea 1390 /* Create a hash table entry. */
f04bb9b2 1391 Fputhash (result, handler, Vdbus_registered_objects_table);
ca4f31ea
MA
1392 }
1393 else
1394 {
1395 /* Send the message. The message is just added to the outgoing
1396 message queue. */
1397 if (!dbus_connection_send (connection, dmessage, NULL))
dcbf5805
MA
1398 {
1399 UNGCPRO;
1400 XD_SIGNAL1 (build_string ("Cannot send message"));
1401 }
13ecc6dc 1402
ca4f31ea
MA
1403 result = Qnil;
1404 }
1405
dcbf5805 1406 XD_DEBUG_MESSAGE ("Message sent: %s", XD_OBJECT_TO_STRING (result));
13ecc6dc
MA
1407
1408 /* Cleanup. */
1409 dbus_message_unref (dmessage);
1410
1411 /* Return the result. */
1412 RETURN_UNGCPRO (result);
1413}
1414
3fad2ad2
J
1415/* Read one queued incoming message of the D-Bus BUS.
1416 BUS is either a Lisp symbol, :system or :session, or a string denoting
1417 the bus address. */
3fad2ad2
J
1418static void
1419xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
033b73e2 1420{
a31d47c7 1421 Lisp_Object args, key, value;
033b73e2 1422 struct gcpro gcpro1;
15f16c1b 1423 struct input_event event;
033b73e2
MA
1424 DBusMessage *dmessage;
1425 DBusMessageIter iter;
eb7c7bf5 1426 unsigned int dtype;
dcbf5805 1427 unsigned int mtype;
30217ff0 1428 dbus_uint32_t serial;
08686060 1429 unsigned int ui_serial;
a8e72f4f 1430 const char *uname, *path, *interface, *member;
39abdd4a 1431
033b73e2
MA
1432 dmessage = dbus_connection_pop_message (connection);
1433
1434 /* Return if there is no queued message. */
1435 if (dmessage == NULL)
3fad2ad2 1436 return;
033b73e2
MA
1437
1438 /* Collect the parameters. */
a31d47c7
MA
1439 args = Qnil;
1440 GCPRO1 (args);
033b73e2 1441
033b73e2 1442 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 1443 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 1444 {
17bc8f94
MA
1445 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1446 != DBUS_TYPE_INVALID)
1447 {
1448 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1449 dbus_message_iter_next (&iter);
1450 }
1451 /* The arguments are stored in reverse order. Reorder them. */
1452 args = Fnreverse (args);
033b73e2
MA
1453 }
1454
13ecc6dc
MA
1455 /* Read message type, message serial, unique name, object path,
1456 interface and member from the message. */
367ea173 1457 mtype = dbus_message_get_type (dmessage);
08686060 1458 ui_serial = serial =
367ea173
MA
1459 ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1460 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1461 ? dbus_message_get_reply_serial (dmessage)
1462 : dbus_message_get_serial (dmessage);
1463 uname = dbus_message_get_sender (dmessage);
1464 path = dbus_message_get_path (dmessage);
a8e72f4f 1465 interface = dbus_message_get_interface (dmessage);
367ea173 1466 member = dbus_message_get_member (dmessage);
a8e72f4f 1467
30217ff0 1468 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
dcbf5805 1469 XD_MESSAGE_TYPE_TO_STRING (mtype),
08686060 1470 ui_serial, uname, path, interface, member,
dcbf5805 1471 XD_OBJECT_TO_STRING (args));
17bc8f94 1472
dcbf5805
MA
1473 if (mtype == DBUS_MESSAGE_TYPE_INVALID)
1474 goto cleanup;
1475
1476 else if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1477 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
13ecc6dc
MA
1478 {
1479 /* Search for a registered function of the message. */
dcbf5805
MA
1480 key = list3 (QCdbus_registered_serial, bus,
1481 make_fixnum_or_float (serial));
f04bb9b2 1482 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1483
1484 /* There shall be exactly one entry. Construct an event. */
1485 if (NILP (value))
1486 goto cleanup;
1487
1488 /* Remove the entry. */
f04bb9b2 1489 Fremhash (key, Vdbus_registered_objects_table);
13ecc6dc
MA
1490
1491 /* Construct an event. */
1492 EVENT_INIT (event);
1493 event.kind = DBUS_EVENT;
1494 event.frame_or_window = Qnil;
1495 event.arg = Fcons (value, args);
1496 }
a31d47c7 1497
dcbf5805 1498 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
a31d47c7 1499 {
f04bb9b2
MA
1500 /* Vdbus_registered_objects_table requires non-nil interface and
1501 member. */
13ecc6dc
MA
1502 if ((interface == NULL) || (member == NULL))
1503 goto cleanup;
1504
1505 /* Search for a registered function of the message. */
dcbf5805
MA
1506 key = list4 ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1507 ? QCdbus_registered_method
1508 : QCdbus_registered_signal,
1509 bus, build_string (interface), build_string (member));
f04bb9b2 1510 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1511
1512 /* Loop over the registered functions. Construct an event. */
1513 while (!NILP (value))
a31d47c7 1514 {
13ecc6dc
MA
1515 key = CAR_SAFE (value);
1516 /* key has the structure (UNAME SERVICE PATH HANDLER). */
1517 if (((uname == NULL)
1518 || (NILP (CAR_SAFE (key)))
59d6fe83 1519 || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0))
13ecc6dc
MA
1520 && ((path == NULL)
1521 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1522 || (strcmp (path,
59d6fe83 1523 SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
13ecc6dc
MA
1524 == 0))
1525 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
1526 {
1527 EVENT_INIT (event);
1528 event.kind = DBUS_EVENT;
1529 event.frame_or_window = Qnil;
b4289b64
MA
1530 event.arg
1531 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
13ecc6dc
MA
1532 break;
1533 }
1534 value = CDR_SAFE (value);
a31d47c7 1535 }
13ecc6dc
MA
1536
1537 if (NILP (value))
1538 goto cleanup;
a31d47c7 1539 }
033b73e2 1540
13ecc6dc
MA
1541 /* Add type, serial, uname, path, interface and member to the event. */
1542 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1543 event.arg);
1544 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1545 event.arg);
1546 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1547 event.arg);
1548 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1549 event.arg);
08686060 1550 event.arg = Fcons (make_fixnum_or_float (serial), event.arg);
13ecc6dc
MA
1551 event.arg = Fcons (make_number (mtype), event.arg);
1552
1553 /* Add the bus symbol to the event. */
1554 event.arg = Fcons (bus, event.arg);
1555
1556 /* Store it into the input event queue. */
1557 kbd_buffer_store_event (&event);
1558
dcbf5805 1559 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
13ecc6dc 1560
c1d5ce94 1561 /* Cleanup. */
a8e72f4f 1562 cleanup:
033b73e2 1563 dbus_message_unref (dmessage);
c1d5ce94 1564
3fad2ad2
J
1565 UNGCPRO;
1566}
1567
1568/* Read queued incoming messages of the D-Bus BUS.
1569 BUS is either a Lisp symbol, :system or :session, or a string denoting
1570 the bus address. */
3fad2ad2
J
1571static Lisp_Object
1572xd_read_message (Lisp_Object bus)
1573{
dcbf5805
MA
1574 /* Retrieve bus address. */
1575 DBusConnection *connection = xd_get_connection_address (bus);
3fad2ad2
J
1576
1577 /* Non blocking read of the next available message. */
1578 dbus_connection_read_write (connection, 0);
1579
1580 while (dbus_connection_get_dispatch_status (connection)
1581 != DBUS_DISPATCH_COMPLETE)
1582 xd_read_message_1 (connection, bus);
1583 return Qnil;
033b73e2
MA
1584}
1585
08609ffd
MA
1586/* Callback called when something is ready to read or write. */
1587static void
1588xd_read_queued_messages (int fd, void *data, int for_read)
033b73e2 1589{
0c372655 1590 Lisp_Object busp = Vdbus_registered_buses;
08609ffd 1591 Lisp_Object bus = Qnil;
dcbf5805 1592 Lisp_Object key;
96faeb40 1593
08609ffd
MA
1594 /* Find bus related to fd. */
1595 if (data != NULL)
1596 while (!NILP (busp))
1597 {
dcbf5805
MA
1598 key = CAR_SAFE (CAR_SAFE (busp));
1599 if ((SYMBOLP (key) && XSYMBOL (key) == data)
1600 || (STRINGP (key) && XSTRING (key) == data))
1601 bus = key;
08609ffd
MA
1602 busp = CDR_SAFE (busp);
1603 }
1604
5e617bc2 1605 if (NILP (bus))
08609ffd
MA
1606 return;
1607
1608 /* We ignore all Lisp errors during the call. */
0c372655 1609 xd_in_read_queued_messages = 1;
08609ffd 1610 internal_catch (Qdbus_error, xd_read_message, bus);
0c372655 1611 xd_in_read_queued_messages = 0;
033b73e2
MA
1612}
1613
033b73e2
MA
1614\f
1615void
971de7fb 1616syms_of_dbusbind (void)
033b73e2
MA
1617{
1618
cd3520a4 1619 DEFSYM (Qdbus_init_bus, "dbus-init-bus");
058ed861
MA
1620 defsubr (&Sdbus_init_bus);
1621
cd3520a4 1622 DEFSYM (Qdbus_get_unique_name, "dbus-get-unique-name");
033b73e2
MA
1623 defsubr (&Sdbus_get_unique_name);
1624
dcbf5805
MA
1625 DEFSYM (Qdbus_message_internal, "dbus-message-internal");
1626 defsubr (&Sdbus_message_internal);
17bc8f94 1627
cd3520a4 1628 DEFSYM (Qdbus_error, "dbus-error");
033b73e2
MA
1629 Fput (Qdbus_error, Qerror_conditions,
1630 list2 (Qdbus_error, Qerror));
1631 Fput (Qdbus_error, Qerror_message,
d67b4f80 1632 make_pure_c_string ("D-Bus error"));
033b73e2 1633
cd3520a4
JB
1634 DEFSYM (QCdbus_system_bus, ":system");
1635 DEFSYM (QCdbus_session_bus, ":session");
cd3520a4
JB
1636 DEFSYM (QCdbus_timeout, ":timeout");
1637 DEFSYM (QCdbus_type_byte, ":byte");
1638 DEFSYM (QCdbus_type_boolean, ":boolean");
1639 DEFSYM (QCdbus_type_int16, ":int16");
1640 DEFSYM (QCdbus_type_uint16, ":uint16");
1641 DEFSYM (QCdbus_type_int32, ":int32");
1642 DEFSYM (QCdbus_type_uint32, ":uint32");
1643 DEFSYM (QCdbus_type_int64, ":int64");
1644 DEFSYM (QCdbus_type_uint64, ":uint64");
1645 DEFSYM (QCdbus_type_double, ":double");
1646 DEFSYM (QCdbus_type_string, ":string");
1647 DEFSYM (QCdbus_type_object_path, ":object-path");
1648 DEFSYM (QCdbus_type_signature, ":signature");
da1fec2b 1649#ifdef DBUS_TYPE_UNIX_FD
cd3520a4 1650 DEFSYM (QCdbus_type_unix_fd, ":unix-fd");
da1fec2b 1651#endif
cd3520a4
JB
1652 DEFSYM (QCdbus_type_array, ":array");
1653 DEFSYM (QCdbus_type_variant, ":variant");
1654 DEFSYM (QCdbus_type_struct, ":struct");
1655 DEFSYM (QCdbus_type_dict_entry, ":dict-entry");
dcbf5805
MA
1656 DEFSYM (QCdbus_registered_serial, ":serial");
1657 DEFSYM (QCdbus_registered_method, ":method");
1658 DEFSYM (QCdbus_registered_signal, ":signal");
1659
1660 DEFVAR_LISP ("dbus-compiled-version",
1661 Vdbus_compiled_version,
1662 doc: /* The version of D-Bus Emacs is compiled against. */);
1663#ifdef DBUS_VERSION_STRING
1664 Vdbus_compiled_version = make_pure_c_string (DBUS_VERSION_STRING);
1665#else
1666 Vdbus_compiled_version = Qnil;
1667#endif
1668
1669 DEFVAR_LISP ("dbus-runtime-version",
1670 Vdbus_runtime_version,
1671 doc: /* The version of D-Bus Emacs runs with. */);
1672 {
1673#ifdef DBUS_VERSION
1674 int major, minor, micro;
1675 char s[1024];
1676 dbus_get_version (&major, &minor, &micro);
1677 snprintf (s, sizeof s, "%d.%d.%d", major, minor, micro);
1678 Vdbus_runtime_version = make_string (s, strlen (s));
1679#else
1680 Vdbus_runtime_version = Qnil;
1681#endif
1682 }
1683
1684 DEFVAR_LISP ("dbus-message-type-invalid",
1685 Vdbus_message_type_invalid,
1686 doc: /* This value is never a valid message type. */);
1687 Vdbus_message_type_invalid = make_number (DBUS_MESSAGE_TYPE_INVALID);
1688
1689 DEFVAR_LISP ("dbus-message-type-method-call",
1690 Vdbus_message_type_method_call,
1691 doc: /* Message type of a method call message. */);
1692 Vdbus_message_type_method_call = make_number (DBUS_MESSAGE_TYPE_METHOD_CALL);
1693
1694 DEFVAR_LISP ("dbus-message-type-method-return",
1695 Vdbus_message_type_method_return,
1696 doc: /* Message type of a method return message. */);
1697 Vdbus_message_type_method_return
1698 = make_number (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1699
1700 DEFVAR_LISP ("dbus-message-type-error",
1701 Vdbus_message_type_error,
1702 doc: /* Message type of an error reply message. */);
1703 Vdbus_message_type_error = make_number (DBUS_MESSAGE_TYPE_ERROR);
1704
1705 DEFVAR_LISP ("dbus-message-type-signal",
1706 Vdbus_message_type_signal,
1707 doc: /* Message type of a signal message. */);
1708 Vdbus_message_type_signal = make_number (DBUS_MESSAGE_TYPE_SIGNAL);
54371585 1709
0c372655 1710 DEFVAR_LISP ("dbus-registered-buses",
29208e82 1711 Vdbus_registered_buses,
dcbf5805
MA
1712 doc: /* Alist of D-Bus buses we are polling for messages.
1713
1714The key is the symbol or string of the bus, and the value is the
1715connection address. */);
0c372655
MA
1716 Vdbus_registered_buses = Qnil;
1717
f04bb9b2 1718 DEFVAR_LISP ("dbus-registered-objects-table",
29208e82 1719 Vdbus_registered_objects_table,
39abdd4a 1720 doc: /* Hash table of registered functions for D-Bus.
0c372655 1721
f04bb9b2
MA
1722There are two different uses of the hash table: for accessing
1723registered interfaces properties, targeted by signals or method calls,
1724and for calling handlers in case of non-blocking method call returns.
13ecc6dc 1725
dcbf5805
MA
1726In the first case, the key in the hash table is the list (TYPE BUS
1727INTERFACE MEMBER). TYPE is one of the Lisp symbols `:method',
1728`:signal' or `:property'. BUS is either a Lisp symbol, `:system' or
0c372655
MA
1729`:session', or a string denoting the bus address. INTERFACE is a
1730string which denotes a D-Bus interface, and MEMBER, also a string, is
1731either a method, a signal or a property INTERFACE is offering. All
1732arguments but BUS must not be nil.
a31d47c7 1733
dcbf5805
MA
1734The value in the hash table is a list of quadruple lists \((UNAME
1735SERVICE PATH OBJECT [RULE]) ...). SERVICE is the service name as
1736registered, UNAME is the corresponding unique name. In case of
1737registered methods and properties, UNAME is nil. PATH is the object
1738path of the sending object. All of them can be nil, which means a
1739wildcard then. OBJECT is either the handler to be called when a D-Bus
1740message, which matches the key criteria, arrives (TYPE `:method' and
1741`:signal'), or a cons cell containing the value of the property (TYPE
1742`:property').
13ecc6dc 1743
dcbf5805
MA
1744For entries of type `:signal', there is also a fifth element RULE,
1745which keeps the match string the signal is registered with.
a3de0cbd 1746
dcbf5805 1747In the second case, the key in the hash table is the list (:serial BUS
0c372655
MA
1748SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
1749string denoting the bus address. SERIAL is the serial number of the
1750non-blocking method call, a reply is expected. Both arguments must
1751not be nil. The value in the hash table is HANDLER, the function to
1752be called when the D-Bus reply message arrives. */);
1753 {
1754 Lisp_Object args[2];
1755 args[0] = QCtest;
1756 args[1] = Qequal;
1757 Vdbus_registered_objects_table = Fmake_hash_table (2, args);
1758 }
033b73e2 1759
29208e82 1760 DEFVAR_LISP ("dbus-debug", Vdbus_debug,
39abdd4a 1761 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
1762#ifdef DBUS_DEBUG
1763 Vdbus_debug = Qt;
a79b0f28
MA
1764 /* We can also set environment variable DBUS_VERBOSE=1 in order to
1765 see more traces. This requires libdbus-1 to be configured with
1766 --enable-verbose-mode. */
033b73e2
MA
1767#else
1768 Vdbus_debug = Qnil;
1769#endif
1770
d67b4f80 1771 Fprovide (intern_c_string ("dbusbind"), Qnil);
033b73e2
MA
1772
1773}
1774
1775#endif /* HAVE_DBUS */