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