* dbus.texi (Type Conversion): Introduce `:unix-fd' type mapping.
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2 1/* Elisp bindings for D-Bus.
114f9c96 2 Copyright (C) 2007, 2008, 2009, 2010 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
MA
30
31\f
32/* Subroutines. */
058ed861 33Lisp_Object Qdbus_init_bus;
0c372655 34Lisp_Object Qdbus_close_bus;
033b73e2
MA
35Lisp_Object Qdbus_get_unique_name;
36Lisp_Object Qdbus_call_method;
13ecc6dc 37Lisp_Object Qdbus_call_method_asynchronously;
8c7a4ac5 38Lisp_Object Qdbus_method_return_internal;
13ecc6dc 39Lisp_Object Qdbus_method_error_internal;
033b73e2
MA
40Lisp_Object Qdbus_send_signal;
41Lisp_Object Qdbus_register_signal;
17bc8f94 42Lisp_Object Qdbus_register_method;
033b73e2
MA
43
44/* D-Bus error symbol. */
45Lisp_Object Qdbus_error;
46
47/* Lisp symbols of the system and session buses. */
39abdd4a 48Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 49
90b3fc84
MA
50/* Lisp symbol for method call timeout. */
51Lisp_Object QCdbus_timeout;
52
54371585
MA
53/* Lisp symbols of D-Bus types. */
54Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
55Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
56Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
57Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
58Lisp_Object QCdbus_type_double, QCdbus_type_string;
59Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
60Lisp_Object QCdbus_type_array, QCdbus_type_variant;
61Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
62
0c372655
MA
63/* Registered buses. */
64Lisp_Object Vdbus_registered_buses;
65
39abdd4a 66/* Hash table which keeps function definitions. */
f04bb9b2 67Lisp_Object Vdbus_registered_objects_table;
033b73e2
MA
68
69/* Whether to debug D-Bus. */
70Lisp_Object Vdbus_debug;
71
1dae9197
MA
72/* Whether we are reading a D-Bus event. */
73int xd_in_read_queued_messages = 0;
74
033b73e2
MA
75\f
76/* We use "xd_" and "XD_" as prefix for all internal symbols, because
77 we don't want to poison other namespaces with "dbus_". */
78
1dae9197
MA
79/* Raise a signal. If we are reading events, we cannot signal; we
80 throw to xd_read_queued_messages then. */
81#define XD_SIGNAL1(arg) \
82 do { \
83 if (xd_in_read_queued_messages) \
84 Fthrow (Qdbus_error, Qnil); \
85 else \
86 xsignal1 (Qdbus_error, arg); \
87 } while (0)
88
89#define XD_SIGNAL2(arg1, arg2) \
90 do { \
91 if (xd_in_read_queued_messages) \
92 Fthrow (Qdbus_error, Qnil); \
93 else \
94 xsignal2 (Qdbus_error, arg1, arg2); \
95 } while (0)
96
97#define XD_SIGNAL3(arg1, arg2, arg3) \
98 do { \
99 if (xd_in_read_queued_messages) \
100 Fthrow (Qdbus_error, Qnil); \
101 else \
102 xsignal3 (Qdbus_error, arg1, arg2, arg3); \
103 } while (0)
104
54371585 105/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 106#define XD_ERROR(error) \
17bc8f94 107 do { \
033b73e2 108 char s[1024]; \
4baa2377 109 strncpy (s, error.message, 1023); \
033b73e2
MA
110 dbus_error_free (&error); \
111 /* Remove the trailing newline. */ \
112 if (strchr (s, '\n') != NULL) \
113 s[strlen (s) - 1] = '\0'; \
1dae9197 114 XD_SIGNAL1 (build_string (s)); \
17bc8f94 115 } while (0)
033b73e2
MA
116
117/* Macros for debugging. In order to enable them, build with
0c372655 118 "MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
033b73e2
MA
119#ifdef DBUS_DEBUG
120#define XD_DEBUG_MESSAGE(...) \
17bc8f94 121 do { \
033b73e2 122 char s[1024]; \
4baa2377 123 snprintf (s, 1023, __VA_ARGS__); \
033b73e2
MA
124 printf ("%s: %s\n", __func__, s); \
125 message ("%s: %s", __func__, s); \
17bc8f94 126 } while (0)
033b73e2 127#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
128 do { \
129 if (!valid_lisp_object_p (object)) \
130 { \
131 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
1dae9197 132 XD_SIGNAL1 (build_string ("Assertion failure")); \
17bc8f94
MA
133 } \
134 } while (0)
033b73e2
MA
135
136#else /* !DBUS_DEBUG */
17bc8f94
MA
137#define XD_DEBUG_MESSAGE(...) \
138 do { \
139 if (!NILP (Vdbus_debug)) \
140 { \
141 char s[1024]; \
4baa2377 142 snprintf (s, 1023, __VA_ARGS__); \
17bc8f94 143 message ("%s: %s", __func__, s); \
80f9d13b 144 } \
17bc8f94 145 } while (0)
033b73e2
MA
146#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
147#endif
148
87cf1a39
MA
149/* Check whether TYPE is a basic DBusType. */
150#define XD_BASIC_DBUS_TYPE(type) \
151 ((type == DBUS_TYPE_BYTE) \
152 || (type == DBUS_TYPE_BOOLEAN) \
153 || (type == DBUS_TYPE_INT16) \
154 || (type == DBUS_TYPE_UINT16) \
155 || (type == DBUS_TYPE_INT32) \
156 || (type == DBUS_TYPE_UINT32) \
157 || (type == DBUS_TYPE_INT64) \
158 || (type == DBUS_TYPE_UINT64) \
159 || (type == DBUS_TYPE_DOUBLE) \
160 || (type == DBUS_TYPE_STRING) \
161 || (type == DBUS_TYPE_OBJECT_PATH) \
162 || (type == DBUS_TYPE_SIGNATURE))
163
78c38319
MA
164/* This was a macro. On Solaris 2.11 it was said to compile for
165 hours, when optimzation is enabled. So we have transferred it into
166 a function. */
54371585
MA
167/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
168 of the predefined D-Bus type symbols. */
78c38319 169static int
971de7fb 170xd_symbol_to_dbus_type (Lisp_Object object)
78c38319
MA
171{
172 return
173 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
174 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN
175 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16
176 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16
177 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32
178 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32
179 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64
180 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64
181 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE
182 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING
183 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH
184 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE
185 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
186 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
187 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
188 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY
189 : DBUS_TYPE_INVALID);
190}
87cf1a39
MA
191
192/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
193#define XD_DBUS_TYPE_P(object) \
78c38319 194 (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
54371585
MA
195
196/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
197 convert Lisp objects, being arguments of `dbus-call-method' or
198 `dbus-send-signal', into corresponding C values appended as
199 arguments to a D-Bus message. */
87cf1a39
MA
200#define XD_OBJECT_TO_DBUS_TYPE(object) \
201 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
202 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
203 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
204 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
205 : (STRINGP (object)) ? DBUS_TYPE_STRING \
78c38319 206 : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
07a4cb03
MA
207 : (CONSP (object)) \
208 ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
78c38319 209 ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
07a4cb03 210 ? DBUS_TYPE_ARRAY \
78c38319 211 : xd_symbol_to_dbus_type (CAR_SAFE (object))) \
07a4cb03 212 : DBUS_TYPE_ARRAY) \
87cf1a39
MA
213 : DBUS_TYPE_INVALID)
214
215/* Return a list pointer which does not have a Lisp symbol as car. */
a8e72f4f 216#define XD_NEXT_VALUE(object) \
5125905e 217 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
87cf1a39
MA
218
219/* Compute SIGNATURE of OBJECT. It must have a form that it can be
220 used in dbus_message_iter_open_container. DTYPE is the DBusType
221 the object is related to. It is passed as argument, because it
222 cannot be detected in basic type objects, when they are preceded by
223 a type symbol. PARENT_TYPE is the DBusType of a container this
224 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
225 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
78c38319 226static void
971de7fb 227xd_signature (char *signature, unsigned int dtype, unsigned int parent_type, Lisp_Object object)
033b73e2 228{
87cf1a39
MA
229 unsigned int subtype;
230 Lisp_Object elt;
231 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
232
233 elt = object;
033b73e2 234
033b73e2
MA
235 switch (dtype)
236 {
54371585
MA
237 case DBUS_TYPE_BYTE:
238 case DBUS_TYPE_UINT16:
033b73e2 239 case DBUS_TYPE_UINT32:
54371585
MA
240 case DBUS_TYPE_UINT64:
241 CHECK_NATNUM (object);
87cf1a39 242 sprintf (signature, "%c", dtype);
54371585 243 break;
87cf1a39 244
54371585
MA
245 case DBUS_TYPE_BOOLEAN:
246 if (!EQ (object, Qt) && !EQ (object, Qnil))
247 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 248 sprintf (signature, "%c", dtype);
54371585 249 break;
87cf1a39 250
54371585 251 case DBUS_TYPE_INT16:
033b73e2 252 case DBUS_TYPE_INT32:
54371585
MA
253 case DBUS_TYPE_INT64:
254 CHECK_NUMBER (object);
87cf1a39 255 sprintf (signature, "%c", dtype);
54371585 256 break;
87cf1a39 257
033b73e2 258 case DBUS_TYPE_DOUBLE:
54371585 259 CHECK_FLOAT (object);
87cf1a39 260 sprintf (signature, "%c", dtype);
54371585 261 break;
87cf1a39 262
033b73e2 263 case DBUS_TYPE_STRING:
54371585
MA
264 case DBUS_TYPE_OBJECT_PATH:
265 case DBUS_TYPE_SIGNATURE:
266 CHECK_STRING (object);
87cf1a39 267 sprintf (signature, "%c", dtype);
54371585 268 break;
87cf1a39 269
54371585 270 case DBUS_TYPE_ARRAY:
9af5078b 271 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
272 complex element types, we just check the container type, not
273 the whole element's signature. */
54371585 274 CHECK_CONS (object);
87cf1a39 275
5125905e
MA
276 /* Type symbol is optional. */
277 if (EQ (QCdbus_type_array, CAR_SAFE (elt)))
87cf1a39 278 elt = XD_NEXT_VALUE (elt);
5125905e
MA
279
280 /* If the array is empty, DBUS_TYPE_STRING is the default
281 element type. */
282 if (NILP (elt))
283 {
284 subtype = DBUS_TYPE_STRING;
285 strcpy (x, DBUS_TYPE_STRING_AS_STRING);
286 }
287 else
288 {
289 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
290 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
291 }
292
293 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
294 only element, the value of this element is used as he array's
295 element signature. */
296 if ((subtype == DBUS_TYPE_SIGNATURE)
297 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
298 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
299 strcpy (x, SDATA (CAR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39
MA
300
301 while (!NILP (elt))
302 {
5125905e
MA
303 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
304 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
305 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
306 }
307
308 sprintf (signature, "%c%s", dtype, x);
54371585 309 break;
87cf1a39 310
54371585 311 case DBUS_TYPE_VARIANT:
9af5078b 312 /* Check that there is exactly one list element. */
54371585 313 CHECK_CONS (object);
87cf1a39
MA
314
315 elt = XD_NEXT_VALUE (elt);
5125905e
MA
316 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
317 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 318
5125905e 319 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 320 wrong_type_argument (intern ("D-Bus"),
5125905e 321 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39 322
a271e124 323 sprintf (signature, "%c", dtype);
54371585 324 break;
87cf1a39 325
54371585 326 case DBUS_TYPE_STRUCT:
9af5078b
MA
327 /* A struct list might contain any number of elements with
328 different types. No further check needed. */
87cf1a39
MA
329 CHECK_CONS (object);
330
331 elt = XD_NEXT_VALUE (elt);
332
333 /* Compose the signature from the elements. It is enclosed by
334 parentheses. */
335 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
336 while (!NILP (elt))
337 {
5125905e
MA
338 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
339 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 340 strcat (signature, x);
5125905e 341 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39 342 }
0ef50993 343 strcat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
54371585 344 break;
54371585 345
87cf1a39 346 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
347 /* Check that there are exactly two list elements, and the first
348 one is of basic type. The dictionary entry itself must be an
349 element of an array. */
87cf1a39 350 CHECK_CONS (object);
54371585 351
9af5078b 352 /* Check the parent object type. */
87cf1a39
MA
353 if (parent_type != DBUS_TYPE_ARRAY)
354 wrong_type_argument (intern ("D-Bus"), object);
54371585 355
87cf1a39
MA
356 /* Compose the signature from the elements. It is enclosed by
357 curly braces. */
358 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 359
87cf1a39
MA
360 /* First element. */
361 elt = XD_NEXT_VALUE (elt);
5125905e
MA
362 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
363 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 364 strcat (signature, x);
54371585 365
87cf1a39 366 if (!XD_BASIC_DBUS_TYPE (subtype))
5125905e 367 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
54371585 368
87cf1a39 369 /* Second element. */
5125905e
MA
370 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
371 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
372 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 373 strcat (signature, x);
54371585 374
5125905e 375 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 376 wrong_type_argument (intern ("D-Bus"),
5125905e 377 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
54371585 378
87cf1a39 379 /* Closing signature. */
0ef50993 380 strcat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
87cf1a39 381 break;
54371585 382
87cf1a39
MA
383 default:
384 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
385 }
386
87cf1a39
MA
387 XD_DEBUG_MESSAGE ("%s", signature);
388}
54371585 389
87cf1a39
MA
390/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
391 DTYPE must be a valid DBusType. It is used to convert Lisp
392 objects, being arguments of `dbus-call-method' or
393 `dbus-send-signal', into corresponding C values appended as
394 arguments to a D-Bus message. */
78c38319 395static void
971de7fb 396xd_append_arg (unsigned int dtype, Lisp_Object object, DBusMessageIter *iter)
87cf1a39 397{
87cf1a39
MA
398 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
399 DBusMessageIter subiter;
87cf1a39
MA
400
401 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
402 switch (dtype)
403 {
404 case DBUS_TYPE_BYTE:
e454a4a3 405 CHECK_NUMBER (object);
54371585 406 {
8bba1b5c 407 unsigned char val = XUINT (object) & 0xFF;
17bc8f94
MA
408 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
409 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 410 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
411 return;
412 }
87cf1a39 413
17bc8f94
MA
414 case DBUS_TYPE_BOOLEAN:
415 {
416 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
417 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
418 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 419 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
420 return;
421 }
87cf1a39 422
17bc8f94 423 case DBUS_TYPE_INT16:
e454a4a3 424 CHECK_NUMBER (object);
17bc8f94
MA
425 {
426 dbus_int16_t val = XINT (object);
427 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
428 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 429 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
430 return;
431 }
87cf1a39 432
17bc8f94 433 case DBUS_TYPE_UINT16:
e454a4a3 434 CHECK_NUMBER (object);
17bc8f94
MA
435 {
436 dbus_uint16_t val = XUINT (object);
437 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
438 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 439 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
440 return;
441 }
87cf1a39 442
17bc8f94 443 case DBUS_TYPE_INT32:
e454a4a3 444 CHECK_NUMBER (object);
17bc8f94
MA
445 {
446 dbus_int32_t val = XINT (object);
447 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
448 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 449 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
450 return;
451 }
87cf1a39 452
17bc8f94 453 case DBUS_TYPE_UINT32:
e454a4a3 454 CHECK_NUMBER (object);
17bc8f94
MA
455 {
456 dbus_uint32_t val = XUINT (object);
457 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
458 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 459 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
460 return;
461 }
87cf1a39 462
17bc8f94 463 case DBUS_TYPE_INT64:
e454a4a3 464 CHECK_NUMBER (object);
17bc8f94
MA
465 {
466 dbus_int64_t val = XINT (object);
467 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
468 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 469 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
470 return;
471 }
87cf1a39 472
17bc8f94 473 case DBUS_TYPE_UINT64:
e454a4a3 474 CHECK_NUMBER (object);
17bc8f94
MA
475 {
476 dbus_uint64_t val = XUINT (object);
477 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
478 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 479 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94 480 return;
54371585 481 }
87cf1a39 482
17bc8f94 483 case DBUS_TYPE_DOUBLE:
e454a4a3 484 CHECK_FLOAT (object);
f601cdf3
KR
485 {
486 double val = XFLOAT_DATA (object);
487 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
488 if (!dbus_message_iter_append_basic (iter, dtype, &val))
489 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
490 return;
491 }
17bc8f94
MA
492
493 case DBUS_TYPE_STRING:
494 case DBUS_TYPE_OBJECT_PATH:
495 case DBUS_TYPE_SIGNATURE:
e454a4a3 496 CHECK_STRING (object);
17bc8f94 497 {
e454a4a3
SM
498 /* We need to send a valid UTF-8 string. We could encode `object'
499 but by not encoding it, we guarantee it's valid utf-8, even if
500 it contains eight-bit-bytes. Of course, you can still send
501 manually-crafted junk by passing a unibyte string. */
502 char *val = SDATA (object);
17bc8f94
MA
503 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
504 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 505 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
506 return;
507 }
508 }
87cf1a39
MA
509
510 else /* Compound types. */
511 {
512
513 /* All compound types except array have a type symbol. For
514 array, it is optional. Skip it. */
5125905e 515 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
87cf1a39
MA
516 object = XD_NEXT_VALUE (object);
517
518 /* Open new subiteration. */
519 switch (dtype)
520 {
521 case DBUS_TYPE_ARRAY:
5125905e
MA
522 /* An array has only elements of the same type. So it is
523 sufficient to check the first element's signature
524 only. */
525
526 if (NILP (object))
527 /* If the array is empty, DBUS_TYPE_STRING is the default
528 element type. */
529 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
530
531 else
532 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
533 the only element, the value of this element is used as
534 the array's element signature. */
535 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
536 == DBUS_TYPE_SIGNATURE)
537 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
538 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
539 {
540 strcpy (signature, SDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
541 object = CDR_SAFE (XD_NEXT_VALUE (object));
542 }
543
544 else
545 xd_signature (signature,
546 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
547 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
548
549 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
550 SDATA (format2 ("%s", object, Qnil)));
551 if (!dbus_message_iter_open_container (iter, dtype,
552 signature, &subiter))
1dae9197
MA
553 XD_SIGNAL3 (build_string ("Cannot open container"),
554 make_number (dtype), build_string (signature));
5125905e
MA
555 break;
556
87cf1a39 557 case DBUS_TYPE_VARIANT:
5125905e
MA
558 /* A variant has just one element. */
559 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
560 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
561
87cf1a39
MA
562 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
563 SDATA (format2 ("%s", object, Qnil)));
564 if (!dbus_message_iter_open_container (iter, dtype,
565 signature, &subiter))
1dae9197
MA
566 XD_SIGNAL3 (build_string ("Cannot open container"),
567 make_number (dtype), build_string (signature));
87cf1a39
MA
568 break;
569
570 case DBUS_TYPE_STRUCT:
571 case DBUS_TYPE_DICT_ENTRY:
9af5078b 572 /* These containers do not require a signature. */
87cf1a39
MA
573 XD_DEBUG_MESSAGE ("%c %s", dtype,
574 SDATA (format2 ("%s", object, Qnil)));
575 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
1dae9197
MA
576 XD_SIGNAL2 (build_string ("Cannot open container"),
577 make_number (dtype));
87cf1a39
MA
578 break;
579 }
580
581 /* Loop over list elements. */
582 while (!NILP (object))
583 {
5125905e 584 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
87cf1a39
MA
585 object = XD_NEXT_VALUE (object);
586
5125905e 587 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
87cf1a39 588
5125905e 589 object = CDR_SAFE (object);
87cf1a39
MA
590 }
591
9af5078b 592 /* Close the subiteration. */
87cf1a39 593 if (!dbus_message_iter_close_container (iter, &subiter))
1dae9197
MA
594 XD_SIGNAL2 (build_string ("Cannot close container"),
595 make_number (dtype));
87cf1a39 596 }
033b73e2
MA
597}
598
599/* Retrieve C value from a DBusMessageIter structure ITER, and return
600 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
601 D-Bus message must be a valid DBusType. Compound D-Bus types
602 result always in a Lisp list. */
78c38319 603static Lisp_Object
971de7fb 604xd_retrieve_arg (unsigned int dtype, DBusMessageIter *iter)
033b73e2
MA
605{
606
607 switch (dtype)
608 {
9af5078b 609 case DBUS_TYPE_BYTE:
9af5078b 610 {
17bc8f94 611 unsigned int val;
9af5078b 612 dbus_message_iter_get_basic (iter, &val);
17bc8f94 613 val = val & 0xFF;
9af5078b
MA
614 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
615 return make_number (val);
616 }
617
033b73e2
MA
618 case DBUS_TYPE_BOOLEAN:
619 {
620 dbus_bool_t val;
621 dbus_message_iter_get_basic (iter, &val);
87cf1a39 622 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
623 return (val == FALSE) ? Qnil : Qt;
624 }
87cf1a39 625
17bc8f94 626 case DBUS_TYPE_INT16:
1cae01f7
AS
627 {
628 dbus_int16_t val;
629 dbus_message_iter_get_basic (iter, &val);
630 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
631 return make_number (val);
632 }
633
17bc8f94
MA
634 case DBUS_TYPE_UINT16:
635 {
636 dbus_uint16_t val;
637 dbus_message_iter_get_basic (iter, &val);
638 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
639 return make_number (val);
640 }
641
033b73e2 642 case DBUS_TYPE_INT32:
1cae01f7
AS
643 {
644 dbus_int32_t val;
645 dbus_message_iter_get_basic (iter, &val);
646 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
647 return make_fixnum_or_float (val);
648 }
649
033b73e2
MA
650 case DBUS_TYPE_UINT32:
651 {
652 dbus_uint32_t val;
653 dbus_message_iter_get_basic (iter, &val);
17bc8f94 654 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
1cae01f7 655 return make_fixnum_or_float (val);
9af5078b
MA
656 }
657
658 case DBUS_TYPE_INT64:
1cae01f7
AS
659 {
660 dbus_int64_t val;
661 dbus_message_iter_get_basic (iter, &val);
662 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
663 return make_fixnum_or_float (val);
664 }
665
9af5078b
MA
666 case DBUS_TYPE_UINT64:
667 {
668 dbus_uint64_t val;
669 dbus_message_iter_get_basic (iter, &val);
17bc8f94 670 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
9af5078b
MA
671 return make_fixnum_or_float (val);
672 }
673
674 case DBUS_TYPE_DOUBLE:
675 {
676 double val;
677 dbus_message_iter_get_basic (iter, &val);
678 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
679 return make_float (val);
033b73e2 680 }
87cf1a39 681
033b73e2
MA
682 case DBUS_TYPE_STRING:
683 case DBUS_TYPE_OBJECT_PATH:
9af5078b 684 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
685 {
686 char *val;
687 dbus_message_iter_get_basic (iter, &val);
87cf1a39 688 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
689 return build_string (val);
690 }
87cf1a39 691
033b73e2
MA
692 case DBUS_TYPE_ARRAY:
693 case DBUS_TYPE_VARIANT:
694 case DBUS_TYPE_STRUCT:
695 case DBUS_TYPE_DICT_ENTRY:
696 {
697 Lisp_Object result;
698 struct gcpro gcpro1;
033b73e2
MA
699 DBusMessageIter subiter;
700 int subtype;
fa8e045a
MA
701 result = Qnil;
702 GCPRO1 (result);
033b73e2
MA
703 dbus_message_iter_recurse (iter, &subiter);
704 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
705 != DBUS_TYPE_INVALID)
706 {
707 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
708 dbus_message_iter_next (&subiter);
709 }
5125905e 710 XD_DEBUG_MESSAGE ("%c %s", dtype, SDATA (format2 ("%s", result, Qnil)));
033b73e2
MA
711 RETURN_UNGCPRO (Fnreverse (result));
712 }
87cf1a39 713
033b73e2 714 default:
87cf1a39 715 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
716 return Qnil;
717 }
718}
719
0c372655
MA
720/* Initialize D-Bus connection. BUS is either a Lisp symbol, :system
721 or :session, or a string denoting the bus address. It tells which
722 D-Bus to initialize. If RAISE_ERROR is non-zero, signal an error
723 when the connection cannot be initialized. */
78c38319 724static DBusConnection *
2536a4b7 725xd_initialize (Lisp_Object bus, int raise_error)
033b73e2
MA
726{
727 DBusConnection *connection;
728 DBusError derror;
729
730 /* Parameter check. */
0c372655
MA
731 if (!STRINGP (bus))
732 {
733 CHECK_SYMBOL (bus);
734 if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus)))
735 {
736 if (raise_error)
737 XD_SIGNAL2 (build_string ("Wrong bus name"), bus);
738 else
739 return NULL;
740 }
033b73e2 741
0c372655
MA
742 /* We do not want to have an autolaunch for the session bus. */
743 if (EQ (bus, QCdbus_session_bus)
744 && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
745 {
746 if (raise_error)
747 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
748 else
749 return NULL;
750 }
751 }
3f56d3c6 752
033b73e2
MA
753 /* Open a connection to the bus. */
754 dbus_error_init (&derror);
755
0c372655
MA
756 if (STRINGP (bus))
757 connection = dbus_connection_open (SDATA (bus), &derror);
033b73e2 758 else
0c372655
MA
759 if (EQ (bus, QCdbus_system_bus))
760 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
761 else
762 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
033b73e2
MA
763
764 if (dbus_error_is_set (&derror))
0c372655
MA
765 {
766 if (raise_error)
767 XD_ERROR (derror);
768 else
769 connection = NULL;
770 }
771
772 /* If it is not the system or session bus, we must register
773 ourselves. Otherwise, we have called dbus_bus_get, which has
774 configured us to exit if the connection closes - we undo this
775 setting. */
776 if (connection != NULL)
777 {
778 if (STRINGP (bus))
779 dbus_bus_register (connection, &derror);
780 else
781 dbus_connection_set_exit_on_disconnect (connection, FALSE);
782 }
783
784 if (dbus_error_is_set (&derror))
785 {
786 if (raise_error)
787 XD_ERROR (derror);
788 else
789 connection = NULL;
790 }
033b73e2 791
de06a2dd 792 if (connection == NULL && raise_error)
3f56d3c6 793 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 794
c1d5ce94
MA
795 /* Cleanup. */
796 dbus_error_free (&derror);
797
033b73e2
MA
798 /* Return the result. */
799 return connection;
800}
801
3fad2ad2 802/* Return the file descriptor for WATCH, -1 if not found. */
3fad2ad2
J
803static int
804xd_find_watch_fd (DBusWatch *watch)
058ed861 805{
eb4c6ace 806#if HAVE_DBUS_WATCH_GET_UNIX_FD
3fad2ad2
J
807 /* TODO: Reverse these on Win32, which prefers the opposite. */
808 int fd = dbus_watch_get_unix_fd (watch);
809 if (fd == -1)
810 fd = dbus_watch_get_socket (watch);
3f56d3c6 811#else
3fad2ad2 812 int fd = dbus_watch_get_fd (watch);
3f56d3c6 813#endif
3fad2ad2
J
814 return fd;
815}
3f56d3c6 816
08609ffd
MA
817/* Prototype. */
818static void
819xd_read_queued_messages (int fd, void *data, int for_read);
058ed861 820
3fad2ad2 821/* Start monitoring WATCH for possible I/O. */
3fad2ad2
J
822static dbus_bool_t
823xd_add_watch (DBusWatch *watch, void *data)
824{
825 unsigned int flags = dbus_watch_get_flags (watch);
826 int fd = xd_find_watch_fd (watch);
827
828 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
829 fd, flags & DBUS_WATCH_WRITABLE,
830 dbus_watch_get_enabled (watch));
831
832 if (fd == -1)
833 return FALSE;
834
835 if (dbus_watch_get_enabled (watch))
836 {
837 if (flags & DBUS_WATCH_WRITABLE)
08609ffd 838 add_write_fd (fd, xd_read_queued_messages, data);
3fad2ad2 839 if (flags & DBUS_WATCH_READABLE)
08609ffd 840 add_read_fd (fd, xd_read_queued_messages, data);
3fad2ad2 841 }
058ed861
MA
842 return TRUE;
843}
844
3fad2ad2
J
845/* Stop monitoring WATCH for possible I/O.
846 DATA is the used bus, either a string or QCdbus_system_bus or
0c372655 847 QCdbus_session_bus. */
3fad2ad2 848static void
971de7fb 849xd_remove_watch (DBusWatch *watch, void *data)
058ed861 850{
3fad2ad2
J
851 unsigned int flags = dbus_watch_get_flags (watch);
852 int fd = xd_find_watch_fd (watch);
3f56d3c6 853
3fad2ad2
J
854 XD_DEBUG_MESSAGE ("fd %d", fd);
855
08609ffd
MA
856 if (fd == -1)
857 return;
777013f2 858
3fad2ad2
J
859 /* Unset session environment. */
860 if (data != NULL && data == (void*) XHASH (QCdbus_session_bus))
861 {
862 XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
863 unsetenv ("DBUS_SESSION_BUS_ADDRESS");
058ed861
MA
864 }
865
3fad2ad2
J
866 if (flags & DBUS_WATCH_WRITABLE)
867 delete_write_fd (fd);
868 if (flags & DBUS_WATCH_READABLE)
869 delete_read_fd (fd);
870}
871
872/* Toggle monitoring WATCH for possible I/O. */
3fad2ad2
J
873static void
874xd_toggle_watch (DBusWatch *watch, void *data)
875{
876 if (dbus_watch_get_enabled (watch))
877 xd_add_watch (watch, data);
878 else
879 xd_remove_watch (watch, data);
058ed861
MA
880}
881
882DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 1, 0,
0c372655 883 doc: /* Initialize connection to D-Bus BUS. */)
5842a27b 884 (Lisp_Object bus)
058ed861
MA
885{
886 DBusConnection *connection;
887
058ed861 888 /* Open a connection to the bus. */
2536a4b7 889 connection = xd_initialize (bus, TRUE);
058ed861 890
777013f2
MA
891 /* Add the watch functions. We pass also the bus as data, in order
892 to distinguish between the busses in xd_remove_watch. */
058ed861
MA
893 if (!dbus_connection_set_watch_functions (connection,
894 xd_add_watch,
895 xd_remove_watch,
3fad2ad2
J
896 xd_toggle_watch,
897 (void*) XHASH (bus), NULL))
058ed861
MA
898 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
899
0c372655
MA
900 /* Add bus to list of registered buses. */
901 Vdbus_registered_buses = Fcons (bus, Vdbus_registered_buses);
902
a79b0f28
MA
903 /* We do not want to abort. */
904 putenv ("DBUS_FATAL_WARNINGS=0");
905
0c372655
MA
906 /* Return. */
907 return Qnil;
908}
909
910DEFUN ("dbus-close-bus", Fdbus_close_bus, Sdbus_close_bus, 1, 1, 0,
911 doc: /* Close connection to D-Bus BUS. */)
912 (Lisp_Object bus)
913{
914 DBusConnection *connection;
915
916 /* Open a connection to the bus. */
917 connection = xd_initialize (bus, TRUE);
918
919 /* Decrement reference count to the bus. */
920 dbus_connection_unref (connection);
921
922 /* Remove bus from list of registered buses. */
923 Vdbus_registered_buses = Fdelete (bus, Vdbus_registered_buses);
924
058ed861
MA
925 /* Return. */
926 return Qnil;
927}
928
033b73e2
MA
929DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
930 1, 1, 0,
5125905e 931 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
5842a27b 932 (Lisp_Object bus)
033b73e2
MA
933{
934 DBusConnection *connection;
48f7d213 935 const char *name;
033b73e2 936
033b73e2 937 /* Open a connection to the bus. */
2536a4b7 938 connection = xd_initialize (bus, TRUE);
033b73e2
MA
939
940 /* Request the name. */
48f7d213 941 name = dbus_bus_get_unique_name (connection);
033b73e2 942 if (name == NULL)
1dae9197 943 XD_SIGNAL1 (build_string ("No unique name available"));
033b73e2
MA
944
945 /* Return. */
946 return build_string (name);
947}
948
949DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
950 doc: /* Call METHOD on the D-Bus BUS.
951
0c372655
MA
952BUS is either a Lisp symbol, `:system' or `:session', or a string
953denoting the bus address.
033b73e2
MA
954
955SERVICE is the D-Bus service name to be used. PATH is the D-Bus
956object path SERVICE is registered at. INTERFACE is an interface
957offered by SERVICE. It must provide METHOD.
958
90b3fc84 959If the parameter `:timeout' is given, the following integer TIMEOUT
f04bb9b2 960specifies the maximum number of milliseconds the method call must
1574224c 961return. The default value is 25,000. If the method call doesn't
48f7d213 962return in time, a D-Bus error is raised.
90b3fc84 963
033b73e2
MA
964All other arguments ARGS are passed to METHOD as arguments. They are
965converted into D-Bus types via the following rules:
966
967 t and nil => DBUS_TYPE_BOOLEAN
968 number => DBUS_TYPE_UINT32
969 integer => DBUS_TYPE_INT32
970 float => DBUS_TYPE_DOUBLE
971 string => DBUS_TYPE_STRING
87cf1a39 972 list => DBUS_TYPE_ARRAY
033b73e2 973
87cf1a39
MA
974All arguments can be preceded by a type symbol. For details about
975type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
976
977`dbus-call-method' returns the resulting values of METHOD as a list of
978Lisp objects. The type conversion happens the other direction as for
87cf1a39
MA
979input arguments. It follows the mapping rules:
980
981 DBUS_TYPE_BOOLEAN => t or nil
982 DBUS_TYPE_BYTE => number
983 DBUS_TYPE_UINT16 => number
984 DBUS_TYPE_INT16 => integer
9af5078b
MA
985 DBUS_TYPE_UINT32 => number or float
986 DBUS_TYPE_INT32 => integer or float
987 DBUS_TYPE_UINT64 => number or float
988 DBUS_TYPE_INT64 => integer or float
87cf1a39
MA
989 DBUS_TYPE_DOUBLE => float
990 DBUS_TYPE_STRING => string
991 DBUS_TYPE_OBJECT_PATH => string
992 DBUS_TYPE_SIGNATURE => string
993 DBUS_TYPE_ARRAY => list
994 DBUS_TYPE_VARIANT => list
995 DBUS_TYPE_STRUCT => list
996 DBUS_TYPE_DICT_ENTRY => list
997
998Example:
033b73e2
MA
999
1000\(dbus-call-method
52da95fa
MA
1001 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
1002 "org.gnome.seahorse.Keys" "GetKeyField"
033b73e2
MA
1003 "openpgp:657984B8C7A966DD" "simple-name")
1004
1005 => (t ("Philip R. Zimmermann"))
1006
1007If the result of the METHOD call is just one value, the converted Lisp
1008object is returned instead of a list containing this single Lisp object.
1009
1010\(dbus-call-method
52da95fa
MA
1011 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1012 "org.freedesktop.Hal.Device" "GetPropertyString"
033b73e2
MA
1013 "system.kernel.machine")
1014
1015 => "i686"
1016
edd9ab1e 1017usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &optional :timeout TIMEOUT &rest ARGS) */)
5842a27b 1018 (int nargs, register Lisp_Object *args)
033b73e2 1019{
52da95fa 1020 Lisp_Object bus, service, path, interface, method;
033b73e2
MA
1021 Lisp_Object result;
1022 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1023 DBusConnection *connection;
1024 DBusMessage *dmessage;
1025 DBusMessage *reply;
1026 DBusMessageIter iter;
1027 DBusError derror;
eb7c7bf5 1028 unsigned int dtype;
90b3fc84
MA
1029 int timeout = -1;
1030 int i = 5;
87cf1a39 1031 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
1032
1033 /* Check parameters. */
1034 bus = args[0];
52da95fa
MA
1035 service = args[1];
1036 path = args[2];
1037 interface = args[3];
1038 method = args[4];
033b73e2 1039
033b73e2
MA
1040 CHECK_STRING (service);
1041 CHECK_STRING (path);
1042 CHECK_STRING (interface);
52da95fa
MA
1043 CHECK_STRING (method);
1044 GCPRO5 (bus, service, path, interface, method);
033b73e2
MA
1045
1046 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
1047 SDATA (service),
1048 SDATA (path),
52da95fa
MA
1049 SDATA (interface),
1050 SDATA (method));
033b73e2
MA
1051
1052 /* Open a connection to the bus. */
2536a4b7 1053 connection = xd_initialize (bus, TRUE);
033b73e2
MA
1054
1055 /* Create the message. */
5125905e
MA
1056 dmessage = dbus_message_new_method_call (SDATA (service),
1057 SDATA (path),
1058 SDATA (interface),
1059 SDATA (method));
90b3fc84 1060 UNGCPRO;
033b73e2 1061 if (dmessage == NULL)
1dae9197 1062 XD_SIGNAL1 (build_string ("Unable to create a new message"));
90b3fc84
MA
1063
1064 /* Check for timeout parameter. */
1065 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
033b73e2 1066 {
90b3fc84
MA
1067 CHECK_NATNUM (args[i+1]);
1068 timeout = XUINT (args[i+1]);
1069 i = i+2;
033b73e2
MA
1070 }
1071
54371585
MA
1072 /* Initialize parameter list of message. */
1073 dbus_message_iter_init_append (dmessage, &iter);
1074
033b73e2 1075 /* Append parameters to the message. */
90b3fc84 1076 for (; i < nargs; ++i)
033b73e2 1077 {
87cf1a39
MA
1078 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1079 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1080 {
1081 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1082 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1083 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
1084 SDATA (format2 ("%s", args[i], Qnil)),
1085 SDATA (format2 ("%s", args[i+1], Qnil)));
1086 ++i;
1087 }
1088 else
1089 {
1090 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1091 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
1092 SDATA (format2 ("%s", args[i], Qnil)));
1093 }
033b73e2 1094
abe136ee 1095 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
1096 indication that there is no parent type. */
1097 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1098
54371585 1099 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
1100 }
1101
1102 /* Send the message. */
1103 dbus_error_init (&derror);
1104 reply = dbus_connection_send_with_reply_and_block (connection,
1105 dmessage,
90b3fc84 1106 timeout,
033b73e2
MA
1107 &derror);
1108
1109 if (dbus_error_is_set (&derror))
1110 XD_ERROR (derror);
1111
1112 if (reply == NULL)
1dae9197 1113 XD_SIGNAL1 (build_string ("No reply"));
033b73e2
MA
1114
1115 XD_DEBUG_MESSAGE ("Message sent");
1116
1117 /* Collect the results. */
1118 result = Qnil;
1119 GCPRO1 (result);
1120
2c3a8b27 1121 if (dbus_message_iter_init (reply, &iter))
033b73e2 1122 {
2c3a8b27
MH
1123 /* Loop over the parameters of the D-Bus reply message. Construct a
1124 Lisp list, which is returned by `dbus-call-method'. */
8c7a4ac5
MA
1125 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1126 != DBUS_TYPE_INVALID)
2c3a8b27
MH
1127 {
1128 result = Fcons (xd_retrieve_arg (dtype, &iter), result);
1129 dbus_message_iter_next (&iter);
1130 }
033b73e2 1131 }
2c3a8b27 1132 else
033b73e2 1133 {
8c7a4ac5 1134 /* No arguments: just return nil. */
033b73e2
MA
1135 }
1136
1137 /* Cleanup. */
c1d5ce94 1138 dbus_error_free (&derror);
033b73e2
MA
1139 dbus_message_unref (dmessage);
1140 dbus_message_unref (reply);
1141
1142 /* Return the result. If there is only one single Lisp object,
1143 return it as-it-is, otherwise return the reversed list. */
1144 if (XUINT (Flength (result)) == 1)
5125905e 1145 RETURN_UNGCPRO (CAR_SAFE (result));
033b73e2
MA
1146 else
1147 RETURN_UNGCPRO (Fnreverse (result));
1148}
1149
13ecc6dc
MA
1150DEFUN ("dbus-call-method-asynchronously", Fdbus_call_method_asynchronously,
1151 Sdbus_call_method_asynchronously, 6, MANY, 0,
1152 doc: /* Call METHOD on the D-Bus BUS asynchronously.
1153
0c372655
MA
1154BUS is either a Lisp symbol, `:system' or `:session', or a string
1155denoting the bus address.
13ecc6dc
MA
1156
1157SERVICE is the D-Bus service name to be used. PATH is the D-Bus
1158object path SERVICE is registered at. INTERFACE is an interface
1159offered by SERVICE. It must provide METHOD.
1160
1161HANDLER is a Lisp function, which is called when the corresponding
ca4f31ea
MA
1162return message has arrived. If HANDLER is nil, no return message will
1163be expected.
13ecc6dc
MA
1164
1165If the parameter `:timeout' is given, the following integer TIMEOUT
f04bb9b2 1166specifies the maximum number of milliseconds the method call must
1574224c 1167return. The default value is 25,000. If the method call doesn't
13ecc6dc
MA
1168return in time, a D-Bus error is raised.
1169
1170All other arguments ARGS are passed to METHOD as arguments. They are
1171converted into D-Bus types via the following rules:
1172
1173 t and nil => DBUS_TYPE_BOOLEAN
1174 number => DBUS_TYPE_UINT32
1175 integer => DBUS_TYPE_INT32
1176 float => DBUS_TYPE_DOUBLE
1177 string => DBUS_TYPE_STRING
1178 list => DBUS_TYPE_ARRAY
1179
1180All arguments can be preceded by a type symbol. For details about
1181type symbols, see Info node `(dbus)Type Conversion'.
1182
ca4f31ea 1183Unless HANDLER is nil, the function returns a key into the hash table
f04bb9b2
MA
1184`dbus-registered-objects-table'. The corresponding entry in the hash
1185table is removed, when the return message has been arrived, and
13ecc6dc
MA
1186HANDLER is called.
1187
1188Example:
1189
1190\(dbus-call-method-asynchronously
1191 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
1192 "org.freedesktop.Hal.Device" "GetPropertyString" 'message
1193 "system.kernel.machine")
1194
1195 => (:system 2)
1196
1197 -| i686
1198
edd9ab1e 1199usage: (dbus-call-method-asynchronously BUS SERVICE PATH INTERFACE METHOD HANDLER &optional :timeout TIMEOUT &rest ARGS) */)
5842a27b 1200 (int nargs, register Lisp_Object *args)
13ecc6dc
MA
1201{
1202 Lisp_Object bus, service, path, interface, method, handler;
1203 Lisp_Object result;
1204 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1205 DBusConnection *connection;
1206 DBusMessage *dmessage;
1207 DBusMessageIter iter;
1208 unsigned int dtype;
1209 int timeout = -1;
1210 int i = 6;
1211 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1212
1213 /* Check parameters. */
1214 bus = args[0];
1215 service = args[1];
1216 path = args[2];
1217 interface = args[3];
1218 method = args[4];
1219 handler = args[5];
1220
13ecc6dc
MA
1221 CHECK_STRING (service);
1222 CHECK_STRING (path);
1223 CHECK_STRING (interface);
1224 CHECK_STRING (method);
ca4f31ea 1225 if (!NILP (handler) && !FUNCTIONP (handler))
13ecc6dc
MA
1226 wrong_type_argument (intern ("functionp"), handler);
1227 GCPRO6 (bus, service, path, interface, method, handler);
1228
1229 XD_DEBUG_MESSAGE ("%s %s %s %s",
1230 SDATA (service),
1231 SDATA (path),
1232 SDATA (interface),
1233 SDATA (method));
1234
1235 /* Open a connection to the bus. */
2536a4b7 1236 connection = xd_initialize (bus, TRUE);
13ecc6dc
MA
1237
1238 /* Create the message. */
1239 dmessage = dbus_message_new_method_call (SDATA (service),
1240 SDATA (path),
1241 SDATA (interface),
1242 SDATA (method));
1243 if (dmessage == NULL)
1dae9197 1244 XD_SIGNAL1 (build_string ("Unable to create a new message"));
13ecc6dc
MA
1245
1246 /* Check for timeout parameter. */
1247 if ((i+2 <= nargs) && (EQ ((args[i]), QCdbus_timeout)))
1248 {
1249 CHECK_NATNUM (args[i+1]);
1250 timeout = XUINT (args[i+1]);
1251 i = i+2;
1252 }
1253
1254 /* Initialize parameter list of message. */
1255 dbus_message_iter_init_append (dmessage, &iter);
1256
1257 /* Append parameters to the message. */
1258 for (; i < nargs; ++i)
1259 {
1260 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1261 if (XD_DBUS_TYPE_P (args[i]))
1262 {
1263 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1264 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1265 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
1266 SDATA (format2 ("%s", args[i], Qnil)),
1267 SDATA (format2 ("%s", args[i+1], Qnil)));
1268 ++i;
1269 }
1270 else
1271 {
1272 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1273 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
1274 SDATA (format2 ("%s", args[i], Qnil)));
1275 }
1276
1277 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1278 indication that there is no parent type. */
1279 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1280
1281 xd_append_arg (dtype, args[i], &iter);
1282 }
1283
ca4f31ea
MA
1284 if (!NILP (handler))
1285 {
1286 /* Send the message. The message is just added to the outgoing
1287 message queue. */
1288 if (!dbus_connection_send_with_reply (connection, dmessage,
1289 NULL, timeout))
1290 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1291
f04bb9b2 1292 /* The result is the key in Vdbus_registered_objects_table. */
ca4f31ea 1293 result = (list2 (bus, make_number (dbus_message_get_serial (dmessage))));
13ecc6dc 1294
ca4f31ea 1295 /* Create a hash table entry. */
f04bb9b2 1296 Fputhash (result, handler, Vdbus_registered_objects_table);
ca4f31ea
MA
1297 }
1298 else
1299 {
1300 /* Send the message. The message is just added to the outgoing
1301 message queue. */
1302 if (!dbus_connection_send (connection, dmessage, NULL))
1303 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1304
ca4f31ea
MA
1305 result = Qnil;
1306 }
1307
ca4f31ea 1308 XD_DEBUG_MESSAGE ("Message sent");
13ecc6dc
MA
1309
1310 /* Cleanup. */
1311 dbus_message_unref (dmessage);
1312
1313 /* Return the result. */
1314 RETURN_UNGCPRO (result);
1315}
1316
8c7a4ac5
MA
1317DEFUN ("dbus-method-return-internal", Fdbus_method_return_internal,
1318 Sdbus_method_return_internal,
abe136ee 1319 3, MANY, 0,
8c7a4ac5 1320 doc: /* Return for message SERIAL on the D-Bus BUS.
abe136ee
MA
1321This is an internal function, it shall not be used outside dbus.el.
1322
8c7a4ac5 1323usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
5842a27b 1324 (int nargs, register Lisp_Object *args)
abe136ee
MA
1325{
1326 Lisp_Object bus, serial, service;
1327 struct gcpro gcpro1, gcpro2, gcpro3;
1328 DBusConnection *connection;
1329 DBusMessage *dmessage;
1330 DBusMessageIter iter;
1331 unsigned int dtype;
1332 int i;
1333 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1334
1335 /* Check parameters. */
1336 bus = args[0];
1337 serial = args[1];
1338 service = args[2];
1339
abe136ee
MA
1340 CHECK_NUMBER (serial);
1341 CHECK_STRING (service);
1342 GCPRO3 (bus, serial, service);
1343
603f0bf0 1344 XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) XUINT (serial), SDATA (service));
abe136ee
MA
1345
1346 /* Open a connection to the bus. */
2536a4b7 1347 connection = xd_initialize (bus, TRUE);
abe136ee
MA
1348
1349 /* Create the message. */
1350 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1351 if ((dmessage == NULL)
1352 || (!dbus_message_set_reply_serial (dmessage, XUINT (serial)))
1353 || (!dbus_message_set_destination (dmessage, SDATA (service))))
1354 {
1355 UNGCPRO;
1dae9197 1356 XD_SIGNAL1 (build_string ("Unable to create a return message"));
abe136ee
MA
1357 }
1358
1359 UNGCPRO;
1360
1361 /* Initialize parameter list of message. */
1362 dbus_message_iter_init_append (dmessage, &iter);
1363
1364 /* Append parameters to the message. */
1365 for (i = 3; i < nargs; ++i)
1366 {
abe136ee
MA
1367 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1368 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1369 {
1370 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1371 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1372 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-2,
1373 SDATA (format2 ("%s", args[i], Qnil)),
1374 SDATA (format2 ("%s", args[i+1], Qnil)));
1375 ++i;
1376 }
1377 else
1378 {
1379 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1380 XD_DEBUG_MESSAGE ("Parameter%d %s", i-2,
1381 SDATA (format2 ("%s", args[i], Qnil)));
1382 }
abe136ee
MA
1383
1384 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1385 indication that there is no parent type. */
1386 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1387
1388 xd_append_arg (dtype, args[i], &iter);
1389 }
1390
1391 /* Send the message. The message is just added to the outgoing
1392 message queue. */
1393 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1394 XD_SIGNAL1 (build_string ("Cannot send message"));
abe136ee 1395
abe136ee
MA
1396 XD_DEBUG_MESSAGE ("Message sent");
1397
1398 /* Cleanup. */
1399 dbus_message_unref (dmessage);
1400
1401 /* Return. */
1402 return Qt;
1403}
1404
13ecc6dc
MA
1405DEFUN ("dbus-method-error-internal", Fdbus_method_error_internal,
1406 Sdbus_method_error_internal,
1407 3, MANY, 0,
1408 doc: /* Return error message for message SERIAL on the D-Bus BUS.
1409This is an internal function, it shall not be used outside dbus.el.
1410
1411usage: (dbus-method-error-internal BUS SERIAL SERVICE &rest ARGS) */)
5842a27b 1412 (int nargs, register Lisp_Object *args)
13ecc6dc
MA
1413{
1414 Lisp_Object bus, serial, service;
1415 struct gcpro gcpro1, gcpro2, gcpro3;
1416 DBusConnection *connection;
1417 DBusMessage *dmessage;
1418 DBusMessageIter iter;
1419 unsigned int dtype;
1420 int i;
1421 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
1422
1423 /* Check parameters. */
1424 bus = args[0];
1425 serial = args[1];
1426 service = args[2];
1427
13ecc6dc
MA
1428 CHECK_NUMBER (serial);
1429 CHECK_STRING (service);
1430 GCPRO3 (bus, serial, service);
1431
603f0bf0 1432 XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) XUINT (serial), SDATA (service));
13ecc6dc
MA
1433
1434 /* Open a connection to the bus. */
2536a4b7 1435 connection = xd_initialize (bus, TRUE);
13ecc6dc
MA
1436
1437 /* Create the message. */
1438 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1439 if ((dmessage == NULL)
1440 || (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED))
1441 || (!dbus_message_set_reply_serial (dmessage, XUINT (serial)))
1442 || (!dbus_message_set_destination (dmessage, SDATA (service))))
1443 {
1444 UNGCPRO;
1dae9197 1445 XD_SIGNAL1 (build_string ("Unable to create a error message"));
13ecc6dc
MA
1446 }
1447
1448 UNGCPRO;
1449
1450 /* Initialize parameter list of message. */
1451 dbus_message_iter_init_append (dmessage, &iter);
1452
1453 /* Append parameters to the message. */
1454 for (i = 3; i < nargs; ++i)
1455 {
1456 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1457 if (XD_DBUS_TYPE_P (args[i]))
1458 {
1459 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1460 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1461 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-2,
1462 SDATA (format2 ("%s", args[i], Qnil)),
1463 SDATA (format2 ("%s", args[i+1], Qnil)));
1464 ++i;
1465 }
1466 else
1467 {
1468 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1469 XD_DEBUG_MESSAGE ("Parameter%d %s", i-2,
1470 SDATA (format2 ("%s", args[i], Qnil)));
1471 }
1472
1473 /* Check for valid signature. We use DBUS_TYPE_INVALID as
1474 indication that there is no parent type. */
1475 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1476
1477 xd_append_arg (dtype, args[i], &iter);
1478 }
1479
1480 /* Send the message. The message is just added to the outgoing
1481 message queue. */
1482 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1483 XD_SIGNAL1 (build_string ("Cannot send message"));
13ecc6dc 1484
13ecc6dc
MA
1485 XD_DEBUG_MESSAGE ("Message sent");
1486
1487 /* Cleanup. */
1488 dbus_message_unref (dmessage);
1489
1490 /* Return. */
1491 return Qt;
1492}
1493
033b73e2
MA
1494DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
1495 doc: /* Send signal SIGNAL on the D-Bus BUS.
1496
0c372655
MA
1497BUS is either a Lisp symbol, `:system' or `:session', or a string
1498denoting the bus address.
033b73e2
MA
1499
1500SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
1501D-Bus object path SERVICE is registered at. INTERFACE is an interface
1502offered by SERVICE. It must provide signal SIGNAL.
1503
1504All other arguments ARGS are passed to SIGNAL as arguments. They are
1505converted into D-Bus types via the following rules:
1506
1507 t and nil => DBUS_TYPE_BOOLEAN
1508 number => DBUS_TYPE_UINT32
1509 integer => DBUS_TYPE_INT32
1510 float => DBUS_TYPE_DOUBLE
1511 string => DBUS_TYPE_STRING
87cf1a39 1512 list => DBUS_TYPE_ARRAY
033b73e2 1513
87cf1a39
MA
1514All arguments can be preceded by a type symbol. For details about
1515type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
1516
1517Example:
1518
1519\(dbus-send-signal
52da95fa
MA
1520 :session "org.gnu.Emacs" "/org/gnu/Emacs"
1521 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
033b73e2 1522
52da95fa 1523usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
5842a27b 1524 (int nargs, register Lisp_Object *args)
033b73e2 1525{
52da95fa 1526 Lisp_Object bus, service, path, interface, signal;
033b73e2
MA
1527 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1528 DBusConnection *connection;
1529 DBusMessage *dmessage;
54371585 1530 DBusMessageIter iter;
eb7c7bf5 1531 unsigned int dtype;
033b73e2 1532 int i;
87cf1a39 1533 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
1534
1535 /* Check parameters. */
1536 bus = args[0];
52da95fa
MA
1537 service = args[1];
1538 path = args[2];
1539 interface = args[3];
1540 signal = args[4];
033b73e2 1541
033b73e2
MA
1542 CHECK_STRING (service);
1543 CHECK_STRING (path);
1544 CHECK_STRING (interface);
52da95fa
MA
1545 CHECK_STRING (signal);
1546 GCPRO5 (bus, service, path, interface, signal);
033b73e2
MA
1547
1548 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
1549 SDATA (service),
1550 SDATA (path),
52da95fa
MA
1551 SDATA (interface),
1552 SDATA (signal));
033b73e2
MA
1553
1554 /* Open a connection to the bus. */
2536a4b7 1555 connection = xd_initialize (bus, TRUE);
033b73e2
MA
1556
1557 /* Create the message. */
5125905e
MA
1558 dmessage = dbus_message_new_signal (SDATA (path),
1559 SDATA (interface),
1560 SDATA (signal));
033b73e2 1561 UNGCPRO;
90b3fc84 1562 if (dmessage == NULL)
1dae9197 1563 XD_SIGNAL1 (build_string ("Unable to create a new message"));
033b73e2 1564
54371585
MA
1565 /* Initialize parameter list of message. */
1566 dbus_message_iter_init_append (dmessage, &iter);
1567
033b73e2
MA
1568 /* Append parameters to the message. */
1569 for (i = 5; i < nargs; ++i)
1570 {
87cf1a39
MA
1571 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1572 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1573 {
1574 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1575 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1576 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
1577 SDATA (format2 ("%s", args[i], Qnil)),
1578 SDATA (format2 ("%s", args[i+1], Qnil)));
1579 ++i;
1580 }
1581 else
1582 {
1583 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1584 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
1585 SDATA (format2 ("%s", args[i], Qnil)));
1586 }
033b73e2 1587
abe136ee 1588 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
1589 indication that there is no parent type. */
1590 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1591
54371585 1592 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
1593 }
1594
1595 /* Send the message. The message is just added to the outgoing
1596 message queue. */
1597 if (!dbus_connection_send (connection, dmessage, NULL))
1dae9197 1598 XD_SIGNAL1 (build_string ("Cannot send message"));
033b73e2 1599
033b73e2
MA
1600 XD_DEBUG_MESSAGE ("Signal sent");
1601
1602 /* Cleanup. */
1603 dbus_message_unref (dmessage);
1604
1605 /* Return. */
1606 return Qt;
1607}
1608
3fad2ad2
J
1609/* Read one queued incoming message of the D-Bus BUS.
1610 BUS is either a Lisp symbol, :system or :session, or a string denoting
1611 the bus address. */
3fad2ad2
J
1612static void
1613xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
033b73e2 1614{
a31d47c7 1615 Lisp_Object args, key, value;
033b73e2 1616 struct gcpro gcpro1;
15f16c1b 1617 struct input_event event;
033b73e2
MA
1618 DBusMessage *dmessage;
1619 DBusMessageIter iter;
eb7c7bf5 1620 unsigned int dtype;
13ecc6dc 1621 int mtype, serial;
a8e72f4f 1622 const char *uname, *path, *interface, *member;
39abdd4a 1623
033b73e2
MA
1624 dmessage = dbus_connection_pop_message (connection);
1625
1626 /* Return if there is no queued message. */
1627 if (dmessage == NULL)
3fad2ad2 1628 return;
033b73e2
MA
1629
1630 /* Collect the parameters. */
a31d47c7
MA
1631 args = Qnil;
1632 GCPRO1 (args);
033b73e2 1633
033b73e2 1634 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 1635 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 1636 {
17bc8f94
MA
1637 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1638 != DBUS_TYPE_INVALID)
1639 {
1640 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1641 dbus_message_iter_next (&iter);
1642 }
1643 /* The arguments are stored in reverse order. Reorder them. */
1644 args = Fnreverse (args);
033b73e2
MA
1645 }
1646
13ecc6dc
MA
1647 /* Read message type, message serial, unique name, object path,
1648 interface and member from the message. */
367ea173
MA
1649 mtype = dbus_message_get_type (dmessage);
1650 serial =
1651 ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1652 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1653 ? dbus_message_get_reply_serial (dmessage)
1654 : dbus_message_get_serial (dmessage);
1655 uname = dbus_message_get_sender (dmessage);
1656 path = dbus_message_get_path (dmessage);
a8e72f4f 1657 interface = dbus_message_get_interface (dmessage);
367ea173 1658 member = dbus_message_get_member (dmessage);
a8e72f4f 1659
13ecc6dc 1660 XD_DEBUG_MESSAGE ("Event received: %s %d %s %s %s %s %s",
367ea173
MA
1661 (mtype == DBUS_MESSAGE_TYPE_INVALID)
1662 ? "DBUS_MESSAGE_TYPE_INVALID"
1663 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1664 ? "DBUS_MESSAGE_TYPE_METHOD_CALL"
1665 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1666 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN"
1667 : (mtype == DBUS_MESSAGE_TYPE_ERROR)
1668 ? "DBUS_MESSAGE_TYPE_ERROR"
1669 : "DBUS_MESSAGE_TYPE_SIGNAL",
13ecc6dc 1670 serial, uname, path, interface, member,
17bc8f94
MA
1671 SDATA (format2 ("%s", args, Qnil)));
1672
367ea173
MA
1673 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1674 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
13ecc6dc
MA
1675 {
1676 /* Search for a registered function of the message. */
1677 key = list2 (bus, make_number (serial));
f04bb9b2 1678 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1679
1680 /* There shall be exactly one entry. Construct an event. */
1681 if (NILP (value))
1682 goto cleanup;
1683
1684 /* Remove the entry. */
f04bb9b2 1685 Fremhash (key, Vdbus_registered_objects_table);
13ecc6dc
MA
1686
1687 /* Construct an event. */
1688 EVENT_INIT (event);
1689 event.kind = DBUS_EVENT;
1690 event.frame_or_window = Qnil;
1691 event.arg = Fcons (value, args);
1692 }
a31d47c7 1693
13ecc6dc 1694 else /* (mtype != DBUS_MESSAGE_TYPE_METHOD_RETURN) */
a31d47c7 1695 {
f04bb9b2
MA
1696 /* Vdbus_registered_objects_table requires non-nil interface and
1697 member. */
13ecc6dc
MA
1698 if ((interface == NULL) || (member == NULL))
1699 goto cleanup;
1700
1701 /* Search for a registered function of the message. */
1702 key = list3 (bus, build_string (interface), build_string (member));
f04bb9b2 1703 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1704
1705 /* Loop over the registered functions. Construct an event. */
1706 while (!NILP (value))
a31d47c7 1707 {
13ecc6dc
MA
1708 key = CAR_SAFE (value);
1709 /* key has the structure (UNAME SERVICE PATH HANDLER). */
1710 if (((uname == NULL)
1711 || (NILP (CAR_SAFE (key)))
1712 || (strcmp (uname, SDATA (CAR_SAFE (key))) == 0))
1713 && ((path == NULL)
1714 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1715 || (strcmp (path,
1716 SDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1717 == 0))
1718 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
1719 {
1720 EVENT_INIT (event);
1721 event.kind = DBUS_EVENT;
1722 event.frame_or_window = Qnil;
1723 event.arg = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))),
1724 args);
1725 break;
1726 }
1727 value = CDR_SAFE (value);
a31d47c7 1728 }
13ecc6dc
MA
1729
1730 if (NILP (value))
1731 goto cleanup;
a31d47c7 1732 }
033b73e2 1733
13ecc6dc
MA
1734 /* Add type, serial, uname, path, interface and member to the event. */
1735 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1736 event.arg);
1737 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1738 event.arg);
1739 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1740 event.arg);
1741 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1742 event.arg);
1743 event.arg = Fcons (make_number (serial), event.arg);
1744 event.arg = Fcons (make_number (mtype), event.arg);
1745
1746 /* Add the bus symbol to the event. */
1747 event.arg = Fcons (bus, event.arg);
1748
1749 /* Store it into the input event queue. */
1750 kbd_buffer_store_event (&event);
1751
1752 XD_DEBUG_MESSAGE ("Event stored: %s",
1753 SDATA (format2 ("%s", event.arg, Qnil)));
1754
c1d5ce94 1755 /* Cleanup. */
a8e72f4f 1756 cleanup:
033b73e2 1757 dbus_message_unref (dmessage);
c1d5ce94 1758
3fad2ad2
J
1759 UNGCPRO;
1760}
1761
1762/* Read queued incoming messages of the D-Bus BUS.
1763 BUS is either a Lisp symbol, :system or :session, or a string denoting
1764 the bus address. */
3fad2ad2
J
1765static Lisp_Object
1766xd_read_message (Lisp_Object bus)
1767{
1768 /* Open a connection to the bus. */
1769 DBusConnection *connection = xd_initialize (bus, TRUE);
1770
1771 /* Non blocking read of the next available message. */
1772 dbus_connection_read_write (connection, 0);
1773
1774 while (dbus_connection_get_dispatch_status (connection)
1775 != DBUS_DISPATCH_COMPLETE)
1776 xd_read_message_1 (connection, bus);
1777 return Qnil;
033b73e2
MA
1778}
1779
08609ffd
MA
1780/* Callback called when something is ready to read or write. */
1781static void
1782xd_read_queued_messages (int fd, void *data, int for_read)
033b73e2 1783{
0c372655 1784 Lisp_Object busp = Vdbus_registered_buses;
08609ffd 1785 Lisp_Object bus = Qnil;
96faeb40 1786
08609ffd
MA
1787 /* Find bus related to fd. */
1788 if (data != NULL)
1789 while (!NILP (busp))
1790 {
1791 if (data == (void*) XHASH (CAR_SAFE (busp)))
1792 bus = CAR_SAFE (busp);
1793 busp = CDR_SAFE (busp);
1794 }
1795
1796 if (NILP(bus))
1797 return;
1798
1799 /* We ignore all Lisp errors during the call. */
0c372655 1800 xd_in_read_queued_messages = 1;
08609ffd 1801 internal_catch (Qdbus_error, xd_read_message, bus);
0c372655 1802 xd_in_read_queued_messages = 0;
033b73e2
MA
1803}
1804
1805DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
944cc4a8 1806 6, MANY, 0,
033b73e2
MA
1807 doc: /* Register for signal SIGNAL on the D-Bus BUS.
1808
0c372655
MA
1809BUS is either a Lisp symbol, `:system' or `:session', or a string
1810denoting the bus address.
033b73e2 1811
39abdd4a
MA
1812SERVICE is the D-Bus service name used by the sending D-Bus object.
1813It can be either a known name or the unique name of the D-Bus object
1814sending the signal. When SERVICE is nil, related signals from all
1815D-Bus objects shall be accepted.
033b73e2 1816
39abdd4a
MA
1817PATH is the D-Bus object path SERVICE is registered. It can also be
1818nil if the path name of incoming signals shall not be checked.
033b73e2 1819
39abdd4a
MA
1820INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
1821HANDLER is a Lisp function to be called when the signal is received.
944cc4a8
MA
1822It must accept as arguments the values SIGNAL is sending.
1823
1824All other arguments ARGS, if specified, must be strings. They stand
1825for the respective arguments of the signal in their order, and are
1826used for filtering as well. A nil argument might be used to preserve
1827the order.
1828
1829INTERFACE, SIGNAL and HANDLER must not be nil. Example:
033b73e2
MA
1830
1831\(defun my-signal-handler (device)
1832 (message "Device %s added" device))
1833
1834\(dbus-register-signal
52da95fa
MA
1835 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
1836 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
033b73e2 1837
f5306ca3
MA
1838 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
1839 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
033b73e2
MA
1840
1841`dbus-register-signal' returns an object, which can be used in
944cc4a8
MA
1842`dbus-unregister-object' for removing the registration.
1843
1844usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
5842a27b 1845 (int nargs, register Lisp_Object *args)
033b73e2 1846{
944cc4a8
MA
1847 Lisp_Object bus, service, path, interface, signal, handler;
1848 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
17bc8f94 1849 Lisp_Object uname, key, key1, value;
033b73e2 1850 DBusConnection *connection;
944cc4a8 1851 int i;
52da95fa 1852 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
c0894fb9 1853 char x[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
39abdd4a 1854 DBusError derror;
033b73e2
MA
1855
1856 /* Check parameters. */
944cc4a8
MA
1857 bus = args[0];
1858 service = args[1];
1859 path = args[2];
1860 interface = args[3];
1861 signal = args[4];
1862 handler = args[5];
1863
39abdd4a
MA
1864 if (!NILP (service)) CHECK_STRING (service);
1865 if (!NILP (path)) CHECK_STRING (path);
033b73e2 1866 CHECK_STRING (interface);
52da95fa 1867 CHECK_STRING (signal);
17bc8f94
MA
1868 if (!FUNCTIONP (handler))
1869 wrong_type_argument (intern ("functionp"), handler);
944cc4a8 1870 GCPRO6 (bus, service, path, interface, signal, handler);
033b73e2 1871
52da95fa
MA
1872 /* Retrieve unique name of service. If service is a known name, we
1873 will register for the corresponding unique name, if any. Signals
1874 are sent always with the unique name as sender. Note: the unique
1875 name of "org.freedesktop.DBus" is that string itself. */
5125905e
MA
1876 if ((STRINGP (service))
1877 && (SBYTES (service) > 0)
eb7c7bf5
MA
1878 && (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0)
1879 && (strncmp (SDATA (service), ":", 1) != 0))
f5306ca3
MA
1880 {
1881 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1882 /* When there is no unique name, we mark it with an empty
1883 string. */
1884 if (NILP (uname))
fff4e459 1885 uname = empty_unibyte_string;
f5306ca3 1886 }
52da95fa 1887 else
f5306ca3 1888 uname = service;
52da95fa 1889
f5306ca3
MA
1890 /* Create a matching rule if the unique name exists (when no
1891 wildcard). */
5125905e 1892 if (NILP (uname) || (SBYTES (uname) > 0))
f5306ca3
MA
1893 {
1894 /* Open a connection to the bus. */
2536a4b7 1895 connection = xd_initialize (bus, TRUE);
033b73e2 1896
f5306ca3
MA
1897 /* Create a rule to receive related signals. */
1898 sprintf (rule,
1899 "type='signal',interface='%s',member='%s'",
1900 SDATA (interface),
1901 SDATA (signal));
033b73e2 1902
f5306ca3
MA
1903 /* Add unique name and path to the rule if they are non-nil. */
1904 if (!NILP (uname))
c0894fb9
MA
1905 {
1906 sprintf (x, ",sender='%s'", SDATA (uname));
1907 strcat (rule, x);
1908 }
39abdd4a 1909
f5306ca3 1910 if (!NILP (path))
c0894fb9
MA
1911 {
1912 sprintf (x, ",path='%s'", SDATA (path));
1913 strcat (rule, x);
1914 }
39abdd4a 1915
944cc4a8
MA
1916 /* Add arguments to the rule if they are non-nil. */
1917 for (i = 6; i < nargs; ++i)
1918 if (!NILP (args[i]))
1919 {
1920 CHECK_STRING (args[i]);
c0894fb9
MA
1921 sprintf (x, ",arg%d='%s'", i-6, SDATA (args[i]));
1922 strcat (rule, x);
944cc4a8
MA
1923 }
1924
f5306ca3
MA
1925 /* Add the rule to the bus. */
1926 dbus_error_init (&derror);
1927 dbus_bus_add_match (connection, rule, &derror);
1928 if (dbus_error_is_set (&derror))
944cc4a8
MA
1929 {
1930 UNGCPRO;
1931 XD_ERROR (derror);
1932 }
033b73e2 1933
c1d5ce94
MA
1934 /* Cleanup. */
1935 dbus_error_free (&derror);
1936
f5306ca3
MA
1937 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
1938 }
033b73e2 1939
39abdd4a 1940 /* Create a hash table entry. */
a31d47c7 1941 key = list3 (bus, interface, signal);
17bc8f94 1942 key1 = list4 (uname, service, path, handler);
f04bb9b2 1943 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
17bc8f94
MA
1944
1945 if (NILP (Fmember (key1, value)))
f04bb9b2 1946 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
17bc8f94
MA
1947
1948 /* Return object. */
944cc4a8 1949 RETURN_UNGCPRO (list2 (key, list3 (service, path, handler)));
17bc8f94
MA
1950}
1951
1952DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
1953 6, 6, 0,
1954 doc: /* Register for method METHOD on the D-Bus BUS.
1955
0c372655
MA
1956BUS is either a Lisp symbol, `:system' or `:session', or a string
1957denoting the bus address.
17bc8f94
MA
1958
1959SERVICE is the D-Bus service name of the D-Bus object METHOD is
1960registered for. It must be a known name.
1961
1962PATH is the D-Bus object path SERVICE is registered. INTERFACE is the
1963interface offered by SERVICE. It must provide METHOD. HANDLER is a
1964Lisp function to be called when a method call is received. It must
1965accept the input arguments of METHOD. The return value of HANDLER is
abe136ee 1966used for composing the returning D-Bus message. */)
5842a27b 1967 (Lisp_Object bus, Lisp_Object service, Lisp_Object path, Lisp_Object interface, Lisp_Object method, Lisp_Object handler)
17bc8f94
MA
1968{
1969 Lisp_Object key, key1, value;
1970 DBusConnection *connection;
1971 int result;
1972 DBusError derror;
1973
17bc8f94 1974 /* Check parameters. */
17bc8f94
MA
1975 CHECK_STRING (service);
1976 CHECK_STRING (path);
1977 CHECK_STRING (interface);
1978 CHECK_STRING (method);
1979 if (!FUNCTIONP (handler))
1980 wrong_type_argument (intern ("functionp"), handler);
1981 /* TODO: We must check for a valid service name, otherwise there is
1982 a segmentation fault. */
1983
1984 /* Open a connection to the bus. */
2536a4b7 1985 connection = xd_initialize (bus, TRUE);
17bc8f94
MA
1986
1987 /* Request the known name from the bus. We can ignore the result,
1988 it is set to -1 if there is an error - kind of redundancy. */
1989 dbus_error_init (&derror);
1990 result = dbus_bus_request_name (connection, SDATA (service), 0, &derror);
1991 if (dbus_error_is_set (&derror))
1992 XD_ERROR (derror);
1993
f04bb9b2
MA
1994 /* Create a hash table entry. We use nil for the unique name,
1995 because the method might be called from anybody. */
17bc8f94
MA
1996 key = list3 (bus, interface, method);
1997 key1 = list4 (Qnil, service, path, handler);
f04bb9b2 1998 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
a31d47c7 1999
17bc8f94 2000 if (NILP (Fmember (key1, value)))
f04bb9b2 2001 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
033b73e2 2002
c1d5ce94
MA
2003 /* Cleanup. */
2004 dbus_error_free (&derror);
2005
f5306ca3
MA
2006 /* Return object. */
2007 return list2 (key, list3 (service, path, handler));
033b73e2
MA
2008}
2009
033b73e2
MA
2010\f
2011void
971de7fb 2012syms_of_dbusbind (void)
033b73e2
MA
2013{
2014
d67b4f80 2015 Qdbus_init_bus = intern_c_string ("dbus-init-bus");
058ed861
MA
2016 staticpro (&Qdbus_init_bus);
2017 defsubr (&Sdbus_init_bus);
2018
0c372655
MA
2019 Qdbus_close_bus = intern_c_string ("dbus-close-bus");
2020 staticpro (&Qdbus_close_bus);
2021 defsubr (&Sdbus_close_bus);
2022
d67b4f80 2023 Qdbus_get_unique_name = intern_c_string ("dbus-get-unique-name");
033b73e2
MA
2024 staticpro (&Qdbus_get_unique_name);
2025 defsubr (&Sdbus_get_unique_name);
2026
d67b4f80 2027 Qdbus_call_method = intern_c_string ("dbus-call-method");
033b73e2
MA
2028 staticpro (&Qdbus_call_method);
2029 defsubr (&Sdbus_call_method);
2030
d67b4f80 2031 Qdbus_call_method_asynchronously = intern_c_string ("dbus-call-method-asynchronously");
13ecc6dc
MA
2032 staticpro (&Qdbus_call_method_asynchronously);
2033 defsubr (&Sdbus_call_method_asynchronously);
2034
d67b4f80 2035 Qdbus_method_return_internal = intern_c_string ("dbus-method-return-internal");
8c7a4ac5
MA
2036 staticpro (&Qdbus_method_return_internal);
2037 defsubr (&Sdbus_method_return_internal);
abe136ee 2038
d67b4f80 2039 Qdbus_method_error_internal = intern_c_string ("dbus-method-error-internal");
13ecc6dc
MA
2040 staticpro (&Qdbus_method_error_internal);
2041 defsubr (&Sdbus_method_error_internal);
2042
d67b4f80 2043 Qdbus_send_signal = intern_c_string ("dbus-send-signal");
033b73e2
MA
2044 staticpro (&Qdbus_send_signal);
2045 defsubr (&Sdbus_send_signal);
2046
d67b4f80 2047 Qdbus_register_signal = intern_c_string ("dbus-register-signal");
033b73e2
MA
2048 staticpro (&Qdbus_register_signal);
2049 defsubr (&Sdbus_register_signal);
2050
d67b4f80 2051 Qdbus_register_method = intern_c_string ("dbus-register-method");
17bc8f94
MA
2052 staticpro (&Qdbus_register_method);
2053 defsubr (&Sdbus_register_method);
2054
d67b4f80 2055 Qdbus_error = intern_c_string ("dbus-error");
033b73e2
MA
2056 staticpro (&Qdbus_error);
2057 Fput (Qdbus_error, Qerror_conditions,
2058 list2 (Qdbus_error, Qerror));
2059 Fput (Qdbus_error, Qerror_message,
d67b4f80 2060 make_pure_c_string ("D-Bus error"));
033b73e2 2061
d67b4f80 2062 QCdbus_system_bus = intern_c_string (":system");
39abdd4a
MA
2063 staticpro (&QCdbus_system_bus);
2064
d67b4f80 2065 QCdbus_session_bus = intern_c_string (":session");
39abdd4a 2066 staticpro (&QCdbus_session_bus);
033b73e2 2067
d67b4f80 2068 QCdbus_timeout = intern_c_string (":timeout");
90b3fc84
MA
2069 staticpro (&QCdbus_timeout);
2070
d67b4f80 2071 QCdbus_type_byte = intern_c_string (":byte");
54371585
MA
2072 staticpro (&QCdbus_type_byte);
2073
d67b4f80 2074 QCdbus_type_boolean = intern_c_string (":boolean");
54371585
MA
2075 staticpro (&QCdbus_type_boolean);
2076
d67b4f80 2077 QCdbus_type_int16 = intern_c_string (":int16");
54371585
MA
2078 staticpro (&QCdbus_type_int16);
2079
d67b4f80 2080 QCdbus_type_uint16 = intern_c_string (":uint16");
54371585
MA
2081 staticpro (&QCdbus_type_uint16);
2082
d67b4f80 2083 QCdbus_type_int32 = intern_c_string (":int32");
54371585
MA
2084 staticpro (&QCdbus_type_int32);
2085
d67b4f80 2086 QCdbus_type_uint32 = intern_c_string (":uint32");
54371585
MA
2087 staticpro (&QCdbus_type_uint32);
2088
d67b4f80 2089 QCdbus_type_int64 = intern_c_string (":int64");
54371585
MA
2090 staticpro (&QCdbus_type_int64);
2091
d67b4f80 2092 QCdbus_type_uint64 = intern_c_string (":uint64");
54371585
MA
2093 staticpro (&QCdbus_type_uint64);
2094
d67b4f80 2095 QCdbus_type_double = intern_c_string (":double");
54371585
MA
2096 staticpro (&QCdbus_type_double);
2097
d67b4f80 2098 QCdbus_type_string = intern_c_string (":string");
54371585
MA
2099 staticpro (&QCdbus_type_string);
2100
d67b4f80 2101 QCdbus_type_object_path = intern_c_string (":object-path");
54371585
MA
2102 staticpro (&QCdbus_type_object_path);
2103
d67b4f80 2104 QCdbus_type_signature = intern_c_string (":signature");
54371585
MA
2105 staticpro (&QCdbus_type_signature);
2106
d67b4f80 2107 QCdbus_type_array = intern_c_string (":array");
54371585
MA
2108 staticpro (&QCdbus_type_array);
2109
d67b4f80 2110 QCdbus_type_variant = intern_c_string (":variant");
54371585
MA
2111 staticpro (&QCdbus_type_variant);
2112
d67b4f80 2113 QCdbus_type_struct = intern_c_string (":struct");
54371585
MA
2114 staticpro (&QCdbus_type_struct);
2115
d67b4f80 2116 QCdbus_type_dict_entry = intern_c_string (":dict-entry");
54371585
MA
2117 staticpro (&QCdbus_type_dict_entry);
2118
0c372655
MA
2119 DEFVAR_LISP ("dbus-registered-buses",
2120 &Vdbus_registered_buses,
2121 doc: /* List of D-Bus buses we are polling for messages. */);
2122 Vdbus_registered_buses = Qnil;
2123
f04bb9b2
MA
2124 DEFVAR_LISP ("dbus-registered-objects-table",
2125 &Vdbus_registered_objects_table,
39abdd4a 2126 doc: /* Hash table of registered functions for D-Bus.
0c372655 2127
f04bb9b2
MA
2128There are two different uses of the hash table: for accessing
2129registered interfaces properties, targeted by signals or method calls,
2130and for calling handlers in case of non-blocking method call returns.
13ecc6dc
MA
2131
2132In the first case, the key in the hash table is the list (BUS
0c372655
MA
2133INTERFACE MEMBER). BUS is either a Lisp symbol, `:system' or
2134`:session', or a string denoting the bus address. INTERFACE is a
2135string which denotes a D-Bus interface, and MEMBER, also a string, is
2136either a method, a signal or a property INTERFACE is offering. All
2137arguments but BUS must not be nil.
a31d47c7 2138
f5306ca3 2139The value in the hash table is a list of quadruple lists
f04bb9b2 2140\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...).
a31d47c7 2141SERVICE is the service name as registered, UNAME is the corresponding
f04bb9b2
MA
2142unique name. In case of registered methods and properties, UNAME is
2143nil. PATH is the object path of the sending object. All of them can
2144be nil, which means a wildcard then. OBJECT is either the handler to
2145be called when a D-Bus message, which matches the key criteria,
2146arrives (methods and signals), or a cons cell containing the value of
2147the property.
13ecc6dc 2148
0c372655
MA
2149In the second case, the key in the hash table is the list (BUS
2150SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
2151string denoting the bus address. SERIAL is the serial number of the
2152non-blocking method call, a reply is expected. Both arguments must
2153not be nil. The value in the hash table is HANDLER, the function to
2154be called when the D-Bus reply message arrives. */);
2155 {
2156 Lisp_Object args[2];
2157 args[0] = QCtest;
2158 args[1] = Qequal;
2159 Vdbus_registered_objects_table = Fmake_hash_table (2, args);
2160 }
033b73e2
MA
2161
2162 DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
39abdd4a 2163 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
2164#ifdef DBUS_DEBUG
2165 Vdbus_debug = Qt;
a79b0f28
MA
2166 /* We can also set environment variable DBUS_VERBOSE=1 in order to
2167 see more traces. This requires libdbus-1 to be configured with
2168 --enable-verbose-mode. */
033b73e2
MA
2169#else
2170 Vdbus_debug = Qnil;
2171#endif
2172
d67b4f80 2173 Fprovide (intern_c_string ("dbusbind"), Qnil);
033b73e2
MA
2174
2175}
2176
2177#endif /* HAVE_DBUS */
79f10da0
MB
2178
2179/* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
2180 (do not change this comment) */