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