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