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