(scan_lists): Follow coding convention.
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2 1/* Elisp bindings for D-Bus.
8bba1b5c 2 Copyright (C) 2007, 2008 Free Software Foundation, Inc.
033b73e2
MA
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
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
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA. */
20
21#include "config.h"
22
23#ifdef HAVE_DBUS
24#include <stdlib.h>
f5306ca3 25#include <stdio.h>
033b73e2
MA
26#include <dbus/dbus.h>
27#include "lisp.h"
28#include "frame.h"
29#include "termhooks.h"
30#include "keyboard.h"
31
32\f
33/* Subroutines. */
34Lisp_Object Qdbus_get_unique_name;
35Lisp_Object Qdbus_call_method;
8c7a4ac5 36Lisp_Object Qdbus_method_return_internal;
033b73e2
MA
37Lisp_Object Qdbus_send_signal;
38Lisp_Object Qdbus_register_signal;
17bc8f94 39Lisp_Object Qdbus_register_method;
033b73e2
MA
40
41/* D-Bus error symbol. */
42Lisp_Object Qdbus_error;
43
44/* Lisp symbols of the system and session buses. */
39abdd4a 45Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 46
54371585
MA
47/* Lisp symbols of D-Bus types. */
48Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
49Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
50Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
51Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
52Lisp_Object QCdbus_type_double, QCdbus_type_string;
53Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
54Lisp_Object QCdbus_type_array, QCdbus_type_variant;
55Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
56
39abdd4a
MA
57/* Hash table which keeps function definitions. */
58Lisp_Object Vdbus_registered_functions_table;
033b73e2
MA
59
60/* Whether to debug D-Bus. */
61Lisp_Object Vdbus_debug;
62
63\f
64/* We use "xd_" and "XD_" as prefix for all internal symbols, because
65 we don't want to poison other namespaces with "dbus_". */
66
54371585 67/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 68#define XD_ERROR(error) \
17bc8f94 69 do { \
033b73e2
MA
70 char s[1024]; \
71 strcpy (s, error.message); \
72 dbus_error_free (&error); \
73 /* Remove the trailing newline. */ \
74 if (strchr (s, '\n') != NULL) \
75 s[strlen (s) - 1] = '\0'; \
76 xsignal1 (Qdbus_error, build_string (s)); \
17bc8f94 77 } while (0)
033b73e2
MA
78
79/* Macros for debugging. In order to enable them, build with
17bc8f94 80 "make MYCPPFLAGS='-DDBUS_DEBUG -Wall'". */
033b73e2
MA
81#ifdef DBUS_DEBUG
82#define XD_DEBUG_MESSAGE(...) \
17bc8f94 83 do { \
033b73e2
MA
84 char s[1024]; \
85 sprintf (s, __VA_ARGS__); \
86 printf ("%s: %s\n", __func__, s); \
87 message ("%s: %s", __func__, s); \
17bc8f94 88 } while (0)
033b73e2 89#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
90 do { \
91 if (!valid_lisp_object_p (object)) \
92 { \
93 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
94 xsignal1 (Qdbus_error, build_string ("Assertion failure")); \
95 } \
96 } while (0)
033b73e2
MA
97
98#else /* !DBUS_DEBUG */
17bc8f94
MA
99#define XD_DEBUG_MESSAGE(...) \
100 do { \
101 if (!NILP (Vdbus_debug)) \
102 { \
103 char s[1024]; \
104 sprintf (s, __VA_ARGS__); \
105 message ("%s: %s", __func__, s); \
80f9d13b 106 } \
17bc8f94 107 } while (0)
033b73e2
MA
108#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
109#endif
110
87cf1a39
MA
111/* Check whether TYPE is a basic DBusType. */
112#define XD_BASIC_DBUS_TYPE(type) \
113 ((type == DBUS_TYPE_BYTE) \
114 || (type == DBUS_TYPE_BOOLEAN) \
115 || (type == DBUS_TYPE_INT16) \
116 || (type == DBUS_TYPE_UINT16) \
117 || (type == DBUS_TYPE_INT32) \
118 || (type == DBUS_TYPE_UINT32) \
119 || (type == DBUS_TYPE_INT64) \
120 || (type == DBUS_TYPE_UINT64) \
121 || (type == DBUS_TYPE_DOUBLE) \
122 || (type == DBUS_TYPE_STRING) \
123 || (type == DBUS_TYPE_OBJECT_PATH) \
124 || (type == DBUS_TYPE_SIGNATURE))
125
54371585
MA
126/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
127 of the predefined D-Bus type symbols. */
87cf1a39
MA
128#define XD_SYMBOL_TO_DBUS_TYPE(object) \
129 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE \
130 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN \
131 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16 \
132 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16 \
133 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32 \
134 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32 \
135 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64 \
136 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64 \
137 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE \
138 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING \
139 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH \
140 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE \
141 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY \
142 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT \
143 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT \
144 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY \
145 : DBUS_TYPE_INVALID)
146
147/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
148#define XD_DBUS_TYPE_P(object) \
149 (SYMBOLP (object) && ((XD_SYMBOL_TO_DBUS_TYPE (object) != DBUS_TYPE_INVALID)))
54371585
MA
150
151/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
152 convert Lisp objects, being arguments of `dbus-call-method' or
153 `dbus-send-signal', into corresponding C values appended as
154 arguments to a D-Bus message. */
87cf1a39
MA
155#define XD_OBJECT_TO_DBUS_TYPE(object) \
156 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
157 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
158 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
159 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
160 : (STRINGP (object)) ? DBUS_TYPE_STRING \
161 : (XD_DBUS_TYPE_P (object)) ? XD_SYMBOL_TO_DBUS_TYPE (object) \
5125905e
MA
162 : (CONSP (object)) ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
163 ? XD_SYMBOL_TO_DBUS_TYPE (CAR_SAFE (object)) \
87cf1a39
MA
164 : DBUS_TYPE_ARRAY) \
165 : DBUS_TYPE_INVALID)
166
167/* Return a list pointer which does not have a Lisp symbol as car. */
168#define XD_NEXT_VALUE(object) \
5125905e 169 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
87cf1a39
MA
170
171/* Compute SIGNATURE of OBJECT. It must have a form that it can be
172 used in dbus_message_iter_open_container. DTYPE is the DBusType
173 the object is related to. It is passed as argument, because it
174 cannot be detected in basic type objects, when they are preceded by
175 a type symbol. PARENT_TYPE is the DBusType of a container this
176 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
177 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
54371585 178void
87cf1a39
MA
179xd_signature(signature, dtype, parent_type, object)
180 char *signature;
181 unsigned int dtype, parent_type;
033b73e2
MA
182 Lisp_Object object;
183{
87cf1a39
MA
184 unsigned int subtype;
185 Lisp_Object elt;
186 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
187
188 elt = object;
033b73e2 189
033b73e2
MA
190 switch (dtype)
191 {
54371585
MA
192 case DBUS_TYPE_BYTE:
193 case DBUS_TYPE_UINT16:
033b73e2 194 case DBUS_TYPE_UINT32:
54371585
MA
195 case DBUS_TYPE_UINT64:
196 CHECK_NATNUM (object);
87cf1a39 197 sprintf (signature, "%c", dtype);
54371585 198 break;
87cf1a39 199
54371585
MA
200 case DBUS_TYPE_BOOLEAN:
201 if (!EQ (object, Qt) && !EQ (object, Qnil))
202 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 203 sprintf (signature, "%c", dtype);
54371585 204 break;
87cf1a39 205
54371585 206 case DBUS_TYPE_INT16:
033b73e2 207 case DBUS_TYPE_INT32:
54371585
MA
208 case DBUS_TYPE_INT64:
209 CHECK_NUMBER (object);
87cf1a39 210 sprintf (signature, "%c", dtype);
54371585 211 break;
87cf1a39 212
033b73e2 213 case DBUS_TYPE_DOUBLE:
54371585 214 CHECK_FLOAT (object);
87cf1a39 215 sprintf (signature, "%c", dtype);
54371585 216 break;
87cf1a39 217
033b73e2 218 case DBUS_TYPE_STRING:
54371585
MA
219 case DBUS_TYPE_OBJECT_PATH:
220 case DBUS_TYPE_SIGNATURE:
221 CHECK_STRING (object);
87cf1a39 222 sprintf (signature, "%c", dtype);
54371585 223 break;
87cf1a39 224
54371585 225 case DBUS_TYPE_ARRAY:
9af5078b 226 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
227 complex element types, we just check the container type, not
228 the whole element's signature. */
54371585 229 CHECK_CONS (object);
87cf1a39 230
5125905e
MA
231 /* Type symbol is optional. */
232 if (EQ (QCdbus_type_array, CAR_SAFE (elt)))
87cf1a39 233 elt = XD_NEXT_VALUE (elt);
5125905e
MA
234
235 /* If the array is empty, DBUS_TYPE_STRING is the default
236 element type. */
237 if (NILP (elt))
238 {
239 subtype = DBUS_TYPE_STRING;
240 strcpy (x, DBUS_TYPE_STRING_AS_STRING);
241 }
242 else
243 {
244 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
245 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
246 }
247
248 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
249 only element, the value of this element is used as he array's
250 element signature. */
251 if ((subtype == DBUS_TYPE_SIGNATURE)
252 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
253 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
254 strcpy (x, SDATA (CAR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39
MA
255
256 while (!NILP (elt))
257 {
5125905e
MA
258 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
259 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
260 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
261 }
262
263 sprintf (signature, "%c%s", dtype, x);
54371585 264 break;
87cf1a39 265
54371585 266 case DBUS_TYPE_VARIANT:
9af5078b 267 /* Check that there is exactly one list element. */
54371585 268 CHECK_CONS (object);
87cf1a39
MA
269
270 elt = XD_NEXT_VALUE (elt);
5125905e
MA
271 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
272 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 273
5125905e 274 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 275 wrong_type_argument (intern ("D-Bus"),
5125905e 276 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39 277
a271e124 278 sprintf (signature, "%c", dtype);
54371585 279 break;
87cf1a39 280
54371585 281 case DBUS_TYPE_STRUCT:
9af5078b
MA
282 /* A struct list might contain any number of elements with
283 different types. No further check needed. */
87cf1a39
MA
284 CHECK_CONS (object);
285
286 elt = XD_NEXT_VALUE (elt);
287
288 /* Compose the signature from the elements. It is enclosed by
289 parentheses. */
290 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
291 while (!NILP (elt))
292 {
5125905e
MA
293 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
294 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 295 strcat (signature, x);
5125905e 296 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
297 }
298 sprintf (signature, "%s%c", signature, DBUS_STRUCT_END_CHAR);
54371585 299 break;
54371585 300
87cf1a39 301 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
302 /* Check that there are exactly two list elements, and the first
303 one is of basic type. The dictionary entry itself must be an
304 element of an array. */
87cf1a39 305 CHECK_CONS (object);
54371585 306
9af5078b 307 /* Check the parent object type. */
87cf1a39
MA
308 if (parent_type != DBUS_TYPE_ARRAY)
309 wrong_type_argument (intern ("D-Bus"), object);
54371585 310
87cf1a39
MA
311 /* Compose the signature from the elements. It is enclosed by
312 curly braces. */
313 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 314
87cf1a39
MA
315 /* First element. */
316 elt = XD_NEXT_VALUE (elt);
5125905e
MA
317 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
318 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 319 strcat (signature, x);
54371585 320
87cf1a39 321 if (!XD_BASIC_DBUS_TYPE (subtype))
5125905e 322 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
54371585 323
87cf1a39 324 /* Second element. */
5125905e
MA
325 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
326 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
327 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 328 strcat (signature, x);
54371585 329
5125905e 330 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 331 wrong_type_argument (intern ("D-Bus"),
5125905e 332 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
54371585 333
87cf1a39
MA
334 /* Closing signature. */
335 sprintf (signature, "%s%c", signature, DBUS_DICT_ENTRY_END_CHAR);
336 break;
54371585 337
87cf1a39
MA
338 default:
339 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
340 }
341
87cf1a39
MA
342 XD_DEBUG_MESSAGE ("%s", signature);
343}
54371585 344
87cf1a39
MA
345/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
346 DTYPE must be a valid DBusType. It is used to convert Lisp
347 objects, being arguments of `dbus-call-method' or
348 `dbus-send-signal', into corresponding C values appended as
349 arguments to a D-Bus message. */
350void
351xd_append_arg (dtype, object, iter)
352 unsigned int dtype;
353 Lisp_Object object;
354 DBusMessageIter *iter;
355{
87cf1a39
MA
356 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
357 DBusMessageIter subiter;
87cf1a39
MA
358
359 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
360 switch (dtype)
361 {
362 case DBUS_TYPE_BYTE:
54371585 363 {
8bba1b5c 364 unsigned char val = XUINT (object) & 0xFF;
17bc8f94
MA
365 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
366 if (!dbus_message_iter_append_basic (iter, dtype, &val))
367 xsignal2 (Qdbus_error,
368 build_string ("Unable to append argument"), object);
369 return;
370 }
87cf1a39 371
17bc8f94
MA
372 case DBUS_TYPE_BOOLEAN:
373 {
374 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
375 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
376 if (!dbus_message_iter_append_basic (iter, dtype, &val))
377 xsignal2 (Qdbus_error,
378 build_string ("Unable to append argument"), object);
379 return;
380 }
87cf1a39 381
17bc8f94
MA
382 case DBUS_TYPE_INT16:
383 {
384 dbus_int16_t val = XINT (object);
385 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
386 if (!dbus_message_iter_append_basic (iter, dtype, &val))
387 xsignal2 (Qdbus_error,
388 build_string ("Unable to append argument"), object);
389 return;
390 }
87cf1a39 391
17bc8f94
MA
392 case DBUS_TYPE_UINT16:
393 {
394 dbus_uint16_t val = XUINT (object);
395 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
396 if (!dbus_message_iter_append_basic (iter, dtype, &val))
397 xsignal2 (Qdbus_error,
398 build_string ("Unable to append argument"), object);
399 return;
400 }
87cf1a39 401
17bc8f94
MA
402 case DBUS_TYPE_INT32:
403 {
404 dbus_int32_t val = XINT (object);
405 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
406 if (!dbus_message_iter_append_basic (iter, dtype, &val))
407 xsignal2 (Qdbus_error,
408 build_string ("Unable to append argument"), object);
409 return;
410 }
87cf1a39 411
17bc8f94
MA
412 case DBUS_TYPE_UINT32:
413 {
414 dbus_uint32_t val = XUINT (object);
415 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
416 if (!dbus_message_iter_append_basic (iter, dtype, &val))
417 xsignal2 (Qdbus_error,
418 build_string ("Unable to append argument"), object);
419 return;
420 }
87cf1a39 421
17bc8f94
MA
422 case DBUS_TYPE_INT64:
423 {
424 dbus_int64_t val = XINT (object);
425 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
426 if (!dbus_message_iter_append_basic (iter, dtype, &val))
427 xsignal2 (Qdbus_error,
428 build_string ("Unable to append argument"), object);
429 return;
430 }
87cf1a39 431
17bc8f94
MA
432 case DBUS_TYPE_UINT64:
433 {
434 dbus_uint64_t val = XUINT (object);
435 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
436 if (!dbus_message_iter_append_basic (iter, dtype, &val))
437 xsignal2 (Qdbus_error,
438 build_string ("Unable to append argument"), object);
439 return;
54371585 440 }
87cf1a39 441
17bc8f94
MA
442 case DBUS_TYPE_DOUBLE:
443 XD_DEBUG_MESSAGE ("%c %f", dtype, XFLOAT_DATA (object));
444 if (!dbus_message_iter_append_basic (iter, dtype,
445 &XFLOAT_DATA (object)))
446 xsignal2 (Qdbus_error,
447 build_string ("Unable to append argument"), object);
448 return;
449
450 case DBUS_TYPE_STRING:
451 case DBUS_TYPE_OBJECT_PATH:
452 case DBUS_TYPE_SIGNATURE:
453 {
454 char *val = SDATA (object);
455 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
456 if (!dbus_message_iter_append_basic (iter, dtype, &val))
457 xsignal2 (Qdbus_error,
458 build_string ("Unable to append argument"), object);
459 return;
460 }
461 }
87cf1a39
MA
462
463 else /* Compound types. */
464 {
465
466 /* All compound types except array have a type symbol. For
467 array, it is optional. Skip it. */
5125905e 468 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
87cf1a39
MA
469 object = XD_NEXT_VALUE (object);
470
471 /* Open new subiteration. */
472 switch (dtype)
473 {
474 case DBUS_TYPE_ARRAY:
5125905e
MA
475 /* An array has only elements of the same type. So it is
476 sufficient to check the first element's signature
477 only. */
478
479 if (NILP (object))
480 /* If the array is empty, DBUS_TYPE_STRING is the default
481 element type. */
482 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
483
484 else
485 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
486 the only element, the value of this element is used as
487 the array's element signature. */
488 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
489 == DBUS_TYPE_SIGNATURE)
490 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
491 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
492 {
493 strcpy (signature, SDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
494 object = CDR_SAFE (XD_NEXT_VALUE (object));
495 }
496
497 else
498 xd_signature (signature,
499 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
500 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
501
502 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
503 SDATA (format2 ("%s", object, Qnil)));
504 if (!dbus_message_iter_open_container (iter, dtype,
505 signature, &subiter))
506 xsignal3 (Qdbus_error,
507 build_string ("Cannot open container"),
508 make_number (dtype), build_string (signature));
509 break;
510
87cf1a39 511 case DBUS_TYPE_VARIANT:
5125905e
MA
512 /* A variant has just one element. */
513 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
514 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
515
87cf1a39
MA
516 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
517 SDATA (format2 ("%s", object, Qnil)));
518 if (!dbus_message_iter_open_container (iter, dtype,
519 signature, &subiter))
520 xsignal3 (Qdbus_error,
521 build_string ("Cannot open container"),
522 make_number (dtype), build_string (signature));
523 break;
524
525 case DBUS_TYPE_STRUCT:
526 case DBUS_TYPE_DICT_ENTRY:
9af5078b 527 /* These containers do not require a signature. */
87cf1a39
MA
528 XD_DEBUG_MESSAGE ("%c %s", dtype,
529 SDATA (format2 ("%s", object, Qnil)));
530 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
531 xsignal2 (Qdbus_error,
532 build_string ("Cannot open container"),
533 make_number (dtype));
534 break;
535 }
536
537 /* Loop over list elements. */
538 while (!NILP (object))
539 {
5125905e 540 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
87cf1a39
MA
541 object = XD_NEXT_VALUE (object);
542
5125905e 543 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
87cf1a39 544
5125905e 545 object = CDR_SAFE (object);
87cf1a39
MA
546 }
547
9af5078b 548 /* Close the subiteration. */
87cf1a39
MA
549 if (!dbus_message_iter_close_container (iter, &subiter))
550 xsignal2 (Qdbus_error,
551 build_string ("Cannot close container"),
552 make_number (dtype));
553 }
033b73e2
MA
554}
555
556/* Retrieve C value from a DBusMessageIter structure ITER, and return
557 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
558 D-Bus message must be a valid DBusType. Compound D-Bus types
559 result always in a Lisp list. */
033b73e2
MA
560Lisp_Object
561xd_retrieve_arg (dtype, iter)
eb7c7bf5 562 unsigned int dtype;
033b73e2
MA
563 DBusMessageIter *iter;
564{
565
566 switch (dtype)
567 {
9af5078b 568 case DBUS_TYPE_BYTE:
9af5078b 569 {
17bc8f94 570 unsigned int val;
9af5078b 571 dbus_message_iter_get_basic (iter, &val);
17bc8f94 572 val = val & 0xFF;
9af5078b
MA
573 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
574 return make_number (val);
575 }
576
033b73e2
MA
577 case DBUS_TYPE_BOOLEAN:
578 {
579 dbus_bool_t val;
580 dbus_message_iter_get_basic (iter, &val);
87cf1a39 581 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
582 return (val == FALSE) ? Qnil : Qt;
583 }
87cf1a39 584
17bc8f94
MA
585 case DBUS_TYPE_INT16:
586 case DBUS_TYPE_UINT16:
587 {
588 dbus_uint16_t val;
589 dbus_message_iter_get_basic (iter, &val);
590 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
591 return make_number (val);
592 }
593
033b73e2
MA
594 case DBUS_TYPE_INT32:
595 case DBUS_TYPE_UINT32:
596 {
b35c64e4
MA
597 /* Assignment to EMACS_INT stops GCC whining about limited
598 range of data type. */
033b73e2 599 dbus_uint32_t val;
b35c64e4 600 EMACS_INT val1;
033b73e2 601 dbus_message_iter_get_basic (iter, &val);
17bc8f94 602 XD_DEBUG_MESSAGE ("%c %d", dtype, val);
b35c64e4
MA
603 val1 = val;
604 return make_fixnum_or_float (val1);
9af5078b
MA
605 }
606
607 case DBUS_TYPE_INT64:
608 case DBUS_TYPE_UINT64:
609 {
610 dbus_uint64_t val;
611 dbus_message_iter_get_basic (iter, &val);
17bc8f94 612 XD_DEBUG_MESSAGE ("%c %d", dtype, (int) val);
9af5078b
MA
613 return make_fixnum_or_float (val);
614 }
615
616 case DBUS_TYPE_DOUBLE:
617 {
618 double val;
619 dbus_message_iter_get_basic (iter, &val);
620 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
621 return make_float (val);
033b73e2 622 }
87cf1a39 623
033b73e2
MA
624 case DBUS_TYPE_STRING:
625 case DBUS_TYPE_OBJECT_PATH:
9af5078b 626 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
627 {
628 char *val;
629 dbus_message_iter_get_basic (iter, &val);
87cf1a39 630 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
631 return build_string (val);
632 }
87cf1a39 633
033b73e2
MA
634 case DBUS_TYPE_ARRAY:
635 case DBUS_TYPE_VARIANT:
636 case DBUS_TYPE_STRUCT:
637 case DBUS_TYPE_DICT_ENTRY:
638 {
639 Lisp_Object result;
640 struct gcpro gcpro1;
641 result = Qnil;
642 GCPRO1 (result);
643 DBusMessageIter subiter;
644 int subtype;
645 dbus_message_iter_recurse (iter, &subiter);
646 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
647 != DBUS_TYPE_INVALID)
648 {
649 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
650 dbus_message_iter_next (&subiter);
651 }
5125905e 652 XD_DEBUG_MESSAGE ("%c %s", dtype, SDATA (format2 ("%s", result, Qnil)));
033b73e2
MA
653 RETURN_UNGCPRO (Fnreverse (result));
654 }
87cf1a39 655
033b73e2 656 default:
87cf1a39 657 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
658 return Qnil;
659 }
660}
661
033b73e2
MA
662/* Initialize D-Bus connection. BUS is a Lisp symbol, either :system
663 or :session. It tells which D-Bus to be initialized. */
664DBusConnection *
665xd_initialize (bus)
666 Lisp_Object bus;
667{
668 DBusConnection *connection;
669 DBusError derror;
670
671 /* Parameter check. */
672 CHECK_SYMBOL (bus);
39abdd4a 673 if (!((EQ (bus, QCdbus_system_bus)) || (EQ (bus, QCdbus_session_bus))))
033b73e2
MA
674 xsignal2 (Qdbus_error, build_string ("Wrong bus name"), bus);
675
676 /* Open a connection to the bus. */
677 dbus_error_init (&derror);
678
39abdd4a 679 if (EQ (bus, QCdbus_system_bus))
033b73e2
MA
680 connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
681 else
682 connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
683
684 if (dbus_error_is_set (&derror))
685 XD_ERROR (derror);
686
687 if (connection == NULL)
688 xsignal2 (Qdbus_error, build_string ("No connection"), bus);
689
690 /* Return the result. */
691 return connection;
692}
693
694DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
695 1, 1, 0,
5125905e 696 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
033b73e2
MA
697 (bus)
698 Lisp_Object bus;
699{
700 DBusConnection *connection;
52da95fa 701 char name[DBUS_MAXIMUM_NAME_LENGTH];
033b73e2
MA
702
703 /* Check parameters. */
704 CHECK_SYMBOL (bus);
705
706 /* Open a connection to the bus. */
707 connection = xd_initialize (bus);
708
709 /* Request the name. */
710 strcpy (name, dbus_bus_get_unique_name (connection));
711 if (name == NULL)
712 xsignal1 (Qdbus_error, build_string ("No unique name available"));
713
714 /* Return. */
715 return build_string (name);
716}
717
718DEFUN ("dbus-call-method", Fdbus_call_method, Sdbus_call_method, 5, MANY, 0,
719 doc: /* Call METHOD on the D-Bus BUS.
720
721BUS is either the symbol `:system' or the symbol `:session'.
722
723SERVICE is the D-Bus service name to be used. PATH is the D-Bus
724object path SERVICE is registered at. INTERFACE is an interface
725offered by SERVICE. It must provide METHOD.
726
727All other arguments ARGS are passed to METHOD as arguments. They are
728converted into D-Bus types via the following rules:
729
730 t and nil => DBUS_TYPE_BOOLEAN
731 number => DBUS_TYPE_UINT32
732 integer => DBUS_TYPE_INT32
733 float => DBUS_TYPE_DOUBLE
734 string => DBUS_TYPE_STRING
87cf1a39 735 list => DBUS_TYPE_ARRAY
033b73e2 736
87cf1a39
MA
737All arguments can be preceded by a type symbol. For details about
738type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
739
740`dbus-call-method' returns the resulting values of METHOD as a list of
741Lisp objects. The type conversion happens the other direction as for
87cf1a39
MA
742input arguments. It follows the mapping rules:
743
744 DBUS_TYPE_BOOLEAN => t or nil
745 DBUS_TYPE_BYTE => number
746 DBUS_TYPE_UINT16 => number
747 DBUS_TYPE_INT16 => integer
9af5078b
MA
748 DBUS_TYPE_UINT32 => number or float
749 DBUS_TYPE_INT32 => integer or float
750 DBUS_TYPE_UINT64 => number or float
751 DBUS_TYPE_INT64 => integer or float
87cf1a39
MA
752 DBUS_TYPE_DOUBLE => float
753 DBUS_TYPE_STRING => string
754 DBUS_TYPE_OBJECT_PATH => string
755 DBUS_TYPE_SIGNATURE => string
756 DBUS_TYPE_ARRAY => list
757 DBUS_TYPE_VARIANT => list
758 DBUS_TYPE_STRUCT => list
759 DBUS_TYPE_DICT_ENTRY => list
760
761Example:
033b73e2
MA
762
763\(dbus-call-method
52da95fa
MA
764 :session "org.gnome.seahorse" "/org/gnome/seahorse/keys/openpgp"
765 "org.gnome.seahorse.Keys" "GetKeyField"
033b73e2
MA
766 "openpgp:657984B8C7A966DD" "simple-name")
767
768 => (t ("Philip R. Zimmermann"))
769
770If the result of the METHOD call is just one value, the converted Lisp
771object is returned instead of a list containing this single Lisp object.
772
773\(dbus-call-method
52da95fa
MA
774 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/devices/computer"
775 "org.freedesktop.Hal.Device" "GetPropertyString"
033b73e2
MA
776 "system.kernel.machine")
777
778 => "i686"
779
52da95fa 780usage: (dbus-call-method BUS SERVICE PATH INTERFACE METHOD &rest ARGS) */)
033b73e2
MA
781 (nargs, args)
782 int nargs;
783 register Lisp_Object *args;
784{
52da95fa 785 Lisp_Object bus, service, path, interface, method;
033b73e2
MA
786 Lisp_Object result;
787 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
788 DBusConnection *connection;
789 DBusMessage *dmessage;
790 DBusMessage *reply;
791 DBusMessageIter iter;
792 DBusError derror;
eb7c7bf5 793 unsigned int dtype;
033b73e2 794 int i;
87cf1a39 795 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
796
797 /* Check parameters. */
798 bus = args[0];
52da95fa
MA
799 service = args[1];
800 path = args[2];
801 interface = args[3];
802 method = args[4];
033b73e2
MA
803
804 CHECK_SYMBOL (bus);
033b73e2
MA
805 CHECK_STRING (service);
806 CHECK_STRING (path);
807 CHECK_STRING (interface);
52da95fa
MA
808 CHECK_STRING (method);
809 GCPRO5 (bus, service, path, interface, method);
033b73e2
MA
810
811 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
812 SDATA (service),
813 SDATA (path),
52da95fa
MA
814 SDATA (interface),
815 SDATA (method));
033b73e2
MA
816
817 /* Open a connection to the bus. */
818 connection = xd_initialize (bus);
819
820 /* Create the message. */
5125905e
MA
821 dmessage = dbus_message_new_method_call (SDATA (service),
822 SDATA (path),
823 SDATA (interface),
824 SDATA (method));
033b73e2
MA
825 if (dmessage == NULL)
826 {
827 UNGCPRO;
828 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
829 }
830
831 UNGCPRO;
832
54371585
MA
833 /* Initialize parameter list of message. */
834 dbus_message_iter_init_append (dmessage, &iter);
835
033b73e2
MA
836 /* Append parameters to the message. */
837 for (i = 5; i < nargs; ++i)
838 {
87cf1a39
MA
839 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
840 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
841 {
842 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
843 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
844 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
845 SDATA (format2 ("%s", args[i], Qnil)),
846 SDATA (format2 ("%s", args[i+1], Qnil)));
847 ++i;
848 }
849 else
850 {
851 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
852 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
853 SDATA (format2 ("%s", args[i], Qnil)));
854 }
033b73e2 855
abe136ee 856 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
857 indication that there is no parent type. */
858 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
859
54371585 860 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
861 }
862
863 /* Send the message. */
864 dbus_error_init (&derror);
865 reply = dbus_connection_send_with_reply_and_block (connection,
866 dmessage,
867 -1,
868 &derror);
869
870 if (dbus_error_is_set (&derror))
871 XD_ERROR (derror);
872
873 if (reply == NULL)
874 xsignal1 (Qdbus_error, build_string ("No reply"));
875
876 XD_DEBUG_MESSAGE ("Message sent");
877
878 /* Collect the results. */
879 result = Qnil;
880 GCPRO1 (result);
881
2c3a8b27 882 if (dbus_message_iter_init (reply, &iter))
033b73e2 883 {
2c3a8b27
MH
884 /* Loop over the parameters of the D-Bus reply message. Construct a
885 Lisp list, which is returned by `dbus-call-method'. */
8c7a4ac5
MA
886 while ((dtype = dbus_message_iter_get_arg_type (&iter))
887 != DBUS_TYPE_INVALID)
2c3a8b27
MH
888 {
889 result = Fcons (xd_retrieve_arg (dtype, &iter), result);
890 dbus_message_iter_next (&iter);
891 }
033b73e2 892 }
2c3a8b27 893 else
033b73e2 894 {
8c7a4ac5 895 /* No arguments: just return nil. */
033b73e2
MA
896 }
897
898 /* Cleanup. */
899 dbus_message_unref (dmessage);
900 dbus_message_unref (reply);
901
902 /* Return the result. If there is only one single Lisp object,
903 return it as-it-is, otherwise return the reversed list. */
904 if (XUINT (Flength (result)) == 1)
5125905e 905 RETURN_UNGCPRO (CAR_SAFE (result));
033b73e2
MA
906 else
907 RETURN_UNGCPRO (Fnreverse (result));
908}
909
8c7a4ac5
MA
910DEFUN ("dbus-method-return-internal", Fdbus_method_return_internal,
911 Sdbus_method_return_internal,
abe136ee 912 3, MANY, 0,
8c7a4ac5 913 doc: /* Return for message SERIAL on the D-Bus BUS.
abe136ee
MA
914This is an internal function, it shall not be used outside dbus.el.
915
8c7a4ac5 916usage: (dbus-method-return-internal BUS SERIAL SERVICE &rest ARGS) */)
abe136ee
MA
917 (nargs, args)
918 int nargs;
919 register Lisp_Object *args;
920{
921 Lisp_Object bus, serial, service;
922 struct gcpro gcpro1, gcpro2, gcpro3;
923 DBusConnection *connection;
924 DBusMessage *dmessage;
925 DBusMessageIter iter;
926 unsigned int dtype;
927 int i;
928 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
929
930 /* Check parameters. */
931 bus = args[0];
932 serial = args[1];
933 service = args[2];
934
935 CHECK_SYMBOL (bus);
936 CHECK_NUMBER (serial);
937 CHECK_STRING (service);
938 GCPRO3 (bus, serial, service);
939
940 XD_DEBUG_MESSAGE ("%d %s ", XUINT (serial), SDATA (service));
941
942 /* Open a connection to the bus. */
943 connection = xd_initialize (bus);
944
945 /* Create the message. */
946 dmessage = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
947 if ((dmessage == NULL)
948 || (!dbus_message_set_reply_serial (dmessage, XUINT (serial)))
949 || (!dbus_message_set_destination (dmessage, SDATA (service))))
950 {
951 UNGCPRO;
952 xsignal1 (Qdbus_error,
953 build_string ("Unable to create a return message"));
954 }
955
956 UNGCPRO;
957
958 /* Initialize parameter list of message. */
959 dbus_message_iter_init_append (dmessage, &iter);
960
961 /* Append parameters to the message. */
962 for (i = 3; i < nargs; ++i)
963 {
abe136ee
MA
964 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
965 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
966 {
967 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
968 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
969 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-2,
970 SDATA (format2 ("%s", args[i], Qnil)),
971 SDATA (format2 ("%s", args[i+1], Qnil)));
972 ++i;
973 }
974 else
975 {
976 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
977 XD_DEBUG_MESSAGE ("Parameter%d %s", i-2,
978 SDATA (format2 ("%s", args[i], Qnil)));
979 }
abe136ee
MA
980
981 /* Check for valid signature. We use DBUS_TYPE_INVALID as
982 indication that there is no parent type. */
983 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
984
985 xd_append_arg (dtype, args[i], &iter);
986 }
987
988 /* Send the message. The message is just added to the outgoing
989 message queue. */
990 if (!dbus_connection_send (connection, dmessage, NULL))
991 xsignal1 (Qdbus_error, build_string ("Cannot send message"));
992
993 /* Flush connection to ensure the message is handled. */
994 dbus_connection_flush (connection);
995
996 XD_DEBUG_MESSAGE ("Message sent");
997
998 /* Cleanup. */
999 dbus_message_unref (dmessage);
1000
1001 /* Return. */
1002 return Qt;
1003}
1004
033b73e2
MA
1005DEFUN ("dbus-send-signal", Fdbus_send_signal, Sdbus_send_signal, 5, MANY, 0,
1006 doc: /* Send signal SIGNAL on the D-Bus BUS.
1007
1008BUS is either the symbol `:system' or the symbol `:session'.
1009
1010SERVICE is the D-Bus service name SIGNAL is sent from. PATH is the
1011D-Bus object path SERVICE is registered at. INTERFACE is an interface
1012offered by SERVICE. It must provide signal SIGNAL.
1013
1014All other arguments ARGS are passed to SIGNAL as arguments. They are
1015converted into D-Bus types via the following rules:
1016
1017 t and nil => DBUS_TYPE_BOOLEAN
1018 number => DBUS_TYPE_UINT32
1019 integer => DBUS_TYPE_INT32
1020 float => DBUS_TYPE_DOUBLE
1021 string => DBUS_TYPE_STRING
87cf1a39 1022 list => DBUS_TYPE_ARRAY
033b73e2 1023
87cf1a39
MA
1024All arguments can be preceded by a type symbol. For details about
1025type symbols, see Info node `(dbus)Type Conversion'.
033b73e2
MA
1026
1027Example:
1028
1029\(dbus-send-signal
52da95fa
MA
1030 :session "org.gnu.Emacs" "/org/gnu/Emacs"
1031 "org.gnu.Emacs.FileManager" "FileModified" "/home/albinus/.emacs")
033b73e2 1032
52da95fa 1033usage: (dbus-send-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS) */)
033b73e2
MA
1034 (nargs, args)
1035 int nargs;
1036 register Lisp_Object *args;
1037{
52da95fa 1038 Lisp_Object bus, service, path, interface, signal;
033b73e2
MA
1039 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
1040 DBusConnection *connection;
1041 DBusMessage *dmessage;
54371585 1042 DBusMessageIter iter;
eb7c7bf5 1043 unsigned int dtype;
033b73e2 1044 int i;
87cf1a39 1045 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2
MA
1046
1047 /* Check parameters. */
1048 bus = args[0];
52da95fa
MA
1049 service = args[1];
1050 path = args[2];
1051 interface = args[3];
1052 signal = args[4];
033b73e2
MA
1053
1054 CHECK_SYMBOL (bus);
033b73e2
MA
1055 CHECK_STRING (service);
1056 CHECK_STRING (path);
1057 CHECK_STRING (interface);
52da95fa
MA
1058 CHECK_STRING (signal);
1059 GCPRO5 (bus, service, path, interface, signal);
033b73e2
MA
1060
1061 XD_DEBUG_MESSAGE ("%s %s %s %s",
033b73e2
MA
1062 SDATA (service),
1063 SDATA (path),
52da95fa
MA
1064 SDATA (interface),
1065 SDATA (signal));
033b73e2
MA
1066
1067 /* Open a connection to the bus. */
1068 connection = xd_initialize (bus);
1069
1070 /* Create the message. */
5125905e
MA
1071 dmessage = dbus_message_new_signal (SDATA (path),
1072 SDATA (interface),
1073 SDATA (signal));
033b73e2
MA
1074 if (dmessage == NULL)
1075 {
1076 UNGCPRO;
1077 xsignal1 (Qdbus_error, build_string ("Unable to create a new message"));
1078 }
1079
1080 UNGCPRO;
1081
54371585
MA
1082 /* Initialize parameter list of message. */
1083 dbus_message_iter_init_append (dmessage, &iter);
1084
033b73e2
MA
1085 /* Append parameters to the message. */
1086 for (i = 5; i < nargs; ++i)
1087 {
87cf1a39
MA
1088 dtype = XD_OBJECT_TO_DBUS_TYPE (args[i]);
1089 if (XD_DBUS_TYPE_P (args[i]))
8c7a4ac5
MA
1090 {
1091 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1092 XD_DEBUG_VALID_LISP_OBJECT_P (args[i+1]);
1093 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
1094 SDATA (format2 ("%s", args[i], Qnil)),
1095 SDATA (format2 ("%s", args[i+1], Qnil)));
1096 ++i;
1097 }
1098 else
1099 {
1100 XD_DEBUG_VALID_LISP_OBJECT_P (args[i]);
1101 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
1102 SDATA (format2 ("%s", args[i], Qnil)));
1103 }
033b73e2 1104
abe136ee 1105 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39
MA
1106 indication that there is no parent type. */
1107 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[i]);
1108
54371585 1109 xd_append_arg (dtype, args[i], &iter);
033b73e2
MA
1110 }
1111
1112 /* Send the message. The message is just added to the outgoing
1113 message queue. */
1114 if (!dbus_connection_send (connection, dmessage, NULL))
1115 xsignal1 (Qdbus_error, build_string ("Cannot send message"));
1116
1117 /* Flush connection to ensure the message is handled. */
1118 dbus_connection_flush (connection);
1119
1120 XD_DEBUG_MESSAGE ("Signal sent");
1121
1122 /* Cleanup. */
1123 dbus_message_unref (dmessage);
1124
1125 /* Return. */
1126 return Qt;
1127}
1128
1129/* Read queued incoming message of the D-Bus BUS. BUS is a Lisp
1130 symbol, either :system or :session. */
96faeb40 1131Lisp_Object
033b73e2
MA
1132xd_read_message (bus)
1133 Lisp_Object bus;
1134{
a31d47c7 1135 Lisp_Object args, key, value;
033b73e2 1136 struct gcpro gcpro1;
15f16c1b 1137 struct input_event event;
033b73e2
MA
1138 DBusConnection *connection;
1139 DBusMessage *dmessage;
1140 DBusMessageIter iter;
eb7c7bf5 1141 unsigned int dtype;
17bc8f94 1142 int mtype;
a31d47c7 1143 char uname[DBUS_MAXIMUM_NAME_LENGTH];
52da95fa
MA
1144 char path[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; /* Unlimited in D-Bus spec. */
1145 char interface[DBUS_MAXIMUM_NAME_LENGTH];
1146 char member[DBUS_MAXIMUM_NAME_LENGTH];
39abdd4a 1147
033b73e2
MA
1148 /* Open a connection to the bus. */
1149 connection = xd_initialize (bus);
1150
1151 /* Non blocking read of the next available message. */
1152 dbus_connection_read_write (connection, 0);
1153 dmessage = dbus_connection_pop_message (connection);
1154
1155 /* Return if there is no queued message. */
1156 if (dmessage == NULL)
17bc8f94 1157 return Qnil;
033b73e2
MA
1158
1159 /* Collect the parameters. */
a31d47c7
MA
1160 args = Qnil;
1161 GCPRO1 (args);
033b73e2 1162
033b73e2 1163 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 1164 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 1165 {
17bc8f94
MA
1166 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1167 != DBUS_TYPE_INVALID)
1168 {
1169 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1170 dbus_message_iter_next (&iter);
1171 }
1172 /* The arguments are stored in reverse order. Reorder them. */
1173 args = Fnreverse (args);
033b73e2
MA
1174 }
1175
17bc8f94
MA
1176 /* Read message type, unique name, object path, interface and member
1177 from the message. */
1178 mtype = dbus_message_get_type (dmessage);
a31d47c7 1179 strcpy (uname, dbus_message_get_sender (dmessage));
39abdd4a
MA
1180 strcpy (path, dbus_message_get_path (dmessage));
1181 strcpy (interface, dbus_message_get_interface (dmessage));
1182 strcpy (member, dbus_message_get_member (dmessage));
1183
17bc8f94
MA
1184 XD_DEBUG_MESSAGE ("Event received: %d %s %s %s %s %s",
1185 mtype, uname, path, interface, member,
1186 SDATA (format2 ("%s", args, Qnil)));
1187
a31d47c7
MA
1188 /* Search for a registered function of the message. */
1189 key = list3 (bus, build_string (interface), build_string (member));
1190 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1191
1192 /* Loop over the registered functions. Construct an event. */
1193 while (!NILP (value))
1194 {
5125905e 1195 key = CAR_SAFE (value);
f5306ca3 1196 /* key has the structure (UNAME SERVICE PATH HANDLER). */
eb7c7bf5 1197 if (((uname == NULL)
5125905e
MA
1198 || (NILP (CAR_SAFE (key)))
1199 || (strcmp (uname, SDATA (CAR_SAFE (key))) == 0))
eb7c7bf5 1200 && ((path == NULL)
5125905e
MA
1201 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1202 || (strcmp (path, SDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1203 == 0))
1204 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
a31d47c7
MA
1205 {
1206 EVENT_INIT (event);
1207 event.kind = DBUS_EVENT;
1208 event.frame_or_window = Qnil;
5125905e
MA
1209 event.arg = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))),
1210 args);
a31d47c7
MA
1211
1212 /* Add uname, path, interface and member to the event. */
1213 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1214 event.arg);
1215 event.arg = Fcons ((interface == NULL
1216 ? Qnil : build_string (interface)),
1217 event.arg);
1218 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1219 event.arg);
1220 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1221 event.arg);
1222
abe136ee
MA
1223 /* Add the message serial if needed, or nil. */
1224 event.arg = Fcons ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL
1225 ? make_number (dbus_message_get_serial (dmessage))
1226 : Qnil),
1227 event.arg);
1228
a31d47c7
MA
1229 /* Add the bus symbol to the event. */
1230 event.arg = Fcons (bus, event.arg);
1231
1232 /* Store it into the input event queue. */
1233 kbd_buffer_store_event (&event);
1234 }
5125905e 1235 value = CDR_SAFE (value);
a31d47c7 1236 }
033b73e2
MA
1237
1238 /* Cleanup. */
1239 dbus_message_unref (dmessage);
17bc8f94 1240 RETURN_UNGCPRO (Qnil);
033b73e2
MA
1241}
1242
1243/* Read queued incoming messages from the system and session buses. */
1244void
1245xd_read_queued_messages ()
1246{
96faeb40 1247
f5306ca3
MA
1248 /* Vdbus_registered_functions_table will be initialized as hash
1249 table in dbus.el. When this package isn't loaded yet, it doesn't
1250 make sense to handle D-Bus messages. Furthermore, we ignore all
1251 Lisp errors during the call. */
96faeb40
MA
1252 if (HASH_TABLE_P (Vdbus_registered_functions_table))
1253 {
1254 internal_condition_case_1 (xd_read_message, QCdbus_system_bus,
1255 Qerror, Fidentity);
1256 internal_condition_case_1 (xd_read_message, QCdbus_session_bus,
1257 Qerror, Fidentity);
1258 }
033b73e2
MA
1259}
1260
1261DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
1262 6, 6, 0,
1263 doc: /* Register for signal SIGNAL on the D-Bus BUS.
1264
1265BUS is either the symbol `:system' or the symbol `:session'.
1266
39abdd4a
MA
1267SERVICE is the D-Bus service name used by the sending D-Bus object.
1268It can be either a known name or the unique name of the D-Bus object
1269sending the signal. When SERVICE is nil, related signals from all
1270D-Bus objects shall be accepted.
033b73e2 1271
39abdd4a
MA
1272PATH is the D-Bus object path SERVICE is registered. It can also be
1273nil if the path name of incoming signals shall not be checked.
033b73e2 1274
39abdd4a
MA
1275INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
1276HANDLER is a Lisp function to be called when the signal is received.
1277It must accept as arguments the values SIGNAL is sending. INTERFACE,
1278SIGNAL and HANDLER must not be nil. Example:
033b73e2
MA
1279
1280\(defun my-signal-handler (device)
1281 (message "Device %s added" device))
1282
1283\(dbus-register-signal
52da95fa
MA
1284 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
1285 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
033b73e2 1286
f5306ca3
MA
1287 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
1288 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
033b73e2
MA
1289
1290`dbus-register-signal' returns an object, which can be used in
17bc8f94 1291`dbus-unregister-object' for removing the registration. */)
52da95fa
MA
1292 (bus, service, path, interface, signal, handler)
1293 Lisp_Object bus, service, path, interface, signal, handler;
033b73e2 1294{
17bc8f94 1295 Lisp_Object uname, key, key1, value;
033b73e2 1296 DBusConnection *connection;
52da95fa 1297 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
39abdd4a 1298 DBusError derror;
033b73e2
MA
1299
1300 /* Check parameters. */
1301 CHECK_SYMBOL (bus);
39abdd4a
MA
1302 if (!NILP (service)) CHECK_STRING (service);
1303 if (!NILP (path)) CHECK_STRING (path);
033b73e2 1304 CHECK_STRING (interface);
52da95fa 1305 CHECK_STRING (signal);
17bc8f94
MA
1306 if (!FUNCTIONP (handler))
1307 wrong_type_argument (intern ("functionp"), handler);
033b73e2 1308
52da95fa
MA
1309 /* Retrieve unique name of service. If service is a known name, we
1310 will register for the corresponding unique name, if any. Signals
1311 are sent always with the unique name as sender. Note: the unique
1312 name of "org.freedesktop.DBus" is that string itself. */
5125905e
MA
1313 if ((STRINGP (service))
1314 && (SBYTES (service) > 0)
eb7c7bf5
MA
1315 && (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0)
1316 && (strncmp (SDATA (service), ":", 1) != 0))
f5306ca3
MA
1317 {
1318 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1319 /* When there is no unique name, we mark it with an empty
1320 string. */
1321 if (NILP (uname))
1322 uname = build_string ("");
1323 }
52da95fa 1324 else
f5306ca3 1325 uname = service;
52da95fa 1326
f5306ca3
MA
1327 /* Create a matching rule if the unique name exists (when no
1328 wildcard). */
5125905e 1329 if (NILP (uname) || (SBYTES (uname) > 0))
f5306ca3
MA
1330 {
1331 /* Open a connection to the bus. */
1332 connection = xd_initialize (bus);
033b73e2 1333
f5306ca3
MA
1334 /* Create a rule to receive related signals. */
1335 sprintf (rule,
1336 "type='signal',interface='%s',member='%s'",
1337 SDATA (interface),
1338 SDATA (signal));
033b73e2 1339
f5306ca3
MA
1340 /* Add unique name and path to the rule if they are non-nil. */
1341 if (!NILP (uname))
1342 sprintf (rule, "%s,sender='%s'", rule, SDATA (uname));
39abdd4a 1343
f5306ca3
MA
1344 if (!NILP (path))
1345 sprintf (rule, "%s,path='%s'", rule, SDATA (path));
39abdd4a 1346
f5306ca3
MA
1347 /* Add the rule to the bus. */
1348 dbus_error_init (&derror);
1349 dbus_bus_add_match (connection, rule, &derror);
1350 if (dbus_error_is_set (&derror))
1351 XD_ERROR (derror);
033b73e2 1352
f5306ca3
MA
1353 XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule);
1354 }
033b73e2 1355
39abdd4a 1356 /* Create a hash table entry. */
a31d47c7 1357 key = list3 (bus, interface, signal);
17bc8f94
MA
1358 key1 = list4 (uname, service, path, handler);
1359 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1360
1361 if (NILP (Fmember (key1, value)))
1362 Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
1363
1364 /* Return object. */
1365 return list2 (key, list3 (service, path, handler));
1366}
1367
1368DEFUN ("dbus-register-method", Fdbus_register_method, Sdbus_register_method,
1369 6, 6, 0,
1370 doc: /* Register for method METHOD on the D-Bus BUS.
1371
1372BUS is either the symbol `:system' or the symbol `:session'.
1373
1374SERVICE is the D-Bus service name of the D-Bus object METHOD is
1375registered for. It must be a known name.
1376
1377PATH is the D-Bus object path SERVICE is registered. INTERFACE is the
1378interface offered by SERVICE. It must provide METHOD. HANDLER is a
1379Lisp function to be called when a method call is received. It must
1380accept the input arguments of METHOD. The return value of HANDLER is
abe136ee 1381used for composing the returning D-Bus message. */)
17bc8f94
MA
1382 (bus, service, path, interface, method, handler)
1383 Lisp_Object bus, service, path, interface, method, handler;
1384{
1385 Lisp_Object key, key1, value;
1386 DBusConnection *connection;
1387 int result;
1388 DBusError derror;
1389
17bc8f94
MA
1390 /* Check parameters. */
1391 CHECK_SYMBOL (bus);
1392 CHECK_STRING (service);
1393 CHECK_STRING (path);
1394 CHECK_STRING (interface);
1395 CHECK_STRING (method);
1396 if (!FUNCTIONP (handler))
1397 wrong_type_argument (intern ("functionp"), handler);
1398 /* TODO: We must check for a valid service name, otherwise there is
1399 a segmentation fault. */
1400
1401 /* Open a connection to the bus. */
1402 connection = xd_initialize (bus);
1403
1404 /* Request the known name from the bus. We can ignore the result,
1405 it is set to -1 if there is an error - kind of redundancy. */
1406 dbus_error_init (&derror);
1407 result = dbus_bus_request_name (connection, SDATA (service), 0, &derror);
1408 if (dbus_error_is_set (&derror))
1409 XD_ERROR (derror);
1410
1411 /* Create a hash table entry. */
1412 key = list3 (bus, interface, method);
1413 key1 = list4 (Qnil, service, path, handler);
a31d47c7
MA
1414 value = Fgethash (key, Vdbus_registered_functions_table, Qnil);
1415
17bc8f94
MA
1416 /* We use nil for the unique name, because the method might be
1417 called from everybody. */
1418 if (NILP (Fmember (key1, value)))
1419 Fputhash (key, Fcons (key1, value), Vdbus_registered_functions_table);
033b73e2 1420
f5306ca3
MA
1421 /* Return object. */
1422 return list2 (key, list3 (service, path, handler));
033b73e2
MA
1423}
1424
033b73e2
MA
1425\f
1426void
1427syms_of_dbusbind ()
1428{
1429
1430 Qdbus_get_unique_name = intern ("dbus-get-unique-name");
1431 staticpro (&Qdbus_get_unique_name);
1432 defsubr (&Sdbus_get_unique_name);
1433
1434 Qdbus_call_method = intern ("dbus-call-method");
1435 staticpro (&Qdbus_call_method);
1436 defsubr (&Sdbus_call_method);
1437
8c7a4ac5
MA
1438 Qdbus_method_return_internal = intern ("dbus-method-return-internal");
1439 staticpro (&Qdbus_method_return_internal);
1440 defsubr (&Sdbus_method_return_internal);
abe136ee 1441
033b73e2
MA
1442 Qdbus_send_signal = intern ("dbus-send-signal");
1443 staticpro (&Qdbus_send_signal);
1444 defsubr (&Sdbus_send_signal);
1445
1446 Qdbus_register_signal = intern ("dbus-register-signal");
1447 staticpro (&Qdbus_register_signal);
1448 defsubr (&Sdbus_register_signal);
1449
17bc8f94
MA
1450 Qdbus_register_method = intern ("dbus-register-method");
1451 staticpro (&Qdbus_register_method);
1452 defsubr (&Sdbus_register_method);
1453
033b73e2
MA
1454 Qdbus_error = intern ("dbus-error");
1455 staticpro (&Qdbus_error);
1456 Fput (Qdbus_error, Qerror_conditions,
1457 list2 (Qdbus_error, Qerror));
1458 Fput (Qdbus_error, Qerror_message,
1459 build_string ("D-Bus error"));
1460
39abdd4a
MA
1461 QCdbus_system_bus = intern (":system");
1462 staticpro (&QCdbus_system_bus);
1463
1464 QCdbus_session_bus = intern (":session");
1465 staticpro (&QCdbus_session_bus);
033b73e2 1466
54371585
MA
1467 QCdbus_type_byte = intern (":byte");
1468 staticpro (&QCdbus_type_byte);
1469
1470 QCdbus_type_boolean = intern (":boolean");
1471 staticpro (&QCdbus_type_boolean);
1472
1473 QCdbus_type_int16 = intern (":int16");
1474 staticpro (&QCdbus_type_int16);
1475
1476 QCdbus_type_uint16 = intern (":uint16");
1477 staticpro (&QCdbus_type_uint16);
1478
1479 QCdbus_type_int32 = intern (":int32");
1480 staticpro (&QCdbus_type_int32);
1481
1482 QCdbus_type_uint32 = intern (":uint32");
1483 staticpro (&QCdbus_type_uint32);
1484
1485 QCdbus_type_int64 = intern (":int64");
1486 staticpro (&QCdbus_type_int64);
1487
1488 QCdbus_type_uint64 = intern (":uint64");
1489 staticpro (&QCdbus_type_uint64);
1490
1491 QCdbus_type_double = intern (":double");
1492 staticpro (&QCdbus_type_double);
1493
1494 QCdbus_type_string = intern (":string");
1495 staticpro (&QCdbus_type_string);
1496
1497 QCdbus_type_object_path = intern (":object-path");
1498 staticpro (&QCdbus_type_object_path);
1499
1500 QCdbus_type_signature = intern (":signature");
1501 staticpro (&QCdbus_type_signature);
1502
1503 QCdbus_type_array = intern (":array");
1504 staticpro (&QCdbus_type_array);
1505
1506 QCdbus_type_variant = intern (":variant");
1507 staticpro (&QCdbus_type_variant);
1508
1509 QCdbus_type_struct = intern (":struct");
1510 staticpro (&QCdbus_type_struct);
1511
1512 QCdbus_type_dict_entry = intern (":dict-entry");
1513 staticpro (&QCdbus_type_dict_entry);
1514
5125905e
MA
1515 DEFVAR_LISP ("dbus-registered-functions-table",
1516 &Vdbus_registered_functions_table,
39abdd4a 1517 doc: /* Hash table of registered functions for D-Bus.
f5306ca3 1518The key in the hash table is the list (BUS INTERFACE MEMBER). BUS is
a31d47c7
MA
1519either the symbol `:system' or the symbol `:session'. INTERFACE is a
1520string which denotes a D-Bus interface, and MEMBER, also a string, is
1521either a method or a signal INTERFACE is offering. All arguments but
1522BUS must not be nil.
1523
f5306ca3
MA
1524The value in the hash table is a list of quadruple lists
1525\((UNAME SERVICE PATH HANDLER) (UNAME SERVICE PATH HANDLER) ...).
a31d47c7
MA
1526SERVICE is the service name as registered, UNAME is the corresponding
1527unique name. PATH is the object path of the sending object. All of
f5306ca3
MA
1528them can be nil, which means a wildcard then. HANDLER is the function
1529to be called when a D-Bus message, which matches the key criteria,
a31d47c7 1530arrives. */);
39abdd4a
MA
1531 /* We initialize Vdbus_registered_functions_table in dbus.el,
1532 because we need to define a hash table function first. */
1533 Vdbus_registered_functions_table = Qnil;
033b73e2
MA
1534
1535 DEFVAR_LISP ("dbus-debug", &Vdbus_debug,
39abdd4a 1536 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
1537#ifdef DBUS_DEBUG
1538 Vdbus_debug = Qt;
1539#else
1540 Vdbus_debug = Qnil;
1541#endif
1542
1543 Fprovide (intern ("dbusbind"), Qnil);
1544
1545}
1546
1547#endif /* HAVE_DBUS */
79f10da0
MB
1548
1549/* arch-tag: 0e828477-b571-4fe4-b559-5c9211bc14b8
1550 (do not change this comment) */