Convert consecutive FSF copyright years to ranges.
[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. */
058ed861 33Lisp_Object Qdbus_init_bus;
0c372655 34Lisp_Object Qdbus_close_bus;
033b73e2
MA
35Lisp_Object Qdbus_get_unique_name;
36Lisp_Object Qdbus_call_method;
13ecc6dc 37Lisp_Object Qdbus_call_method_asynchronously;
8c7a4ac5 38Lisp_Object Qdbus_method_return_internal;
13ecc6dc 39Lisp_Object Qdbus_method_error_internal;
033b73e2 40Lisp_Object Qdbus_send_signal;
5b83ba18 41Lisp_Object Qdbus_register_service;
033b73e2 42Lisp_Object Qdbus_register_signal;
17bc8f94 43Lisp_Object Qdbus_register_method;
033b73e2
MA
44
45/* D-Bus error symbol. */
46Lisp_Object Qdbus_error;
47
48/* Lisp symbols of the system and session buses. */
39abdd4a 49Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 50
90b3fc84
MA
51/* Lisp symbol for method call timeout. */
52Lisp_Object QCdbus_timeout;
53
5b83ba18
MA
54/* Lisp symbols for name request flags. */
55Lisp_Object QCdbus_request_name_allow_replacement;
56Lisp_Object QCdbus_request_name_replace_existing;
57Lisp_Object QCdbus_request_name_do_not_queue;
58
59/* Lisp symbols for name request replies. */
60Lisp_Object QCdbus_request_name_reply_primary_owner;
61Lisp_Object QCdbus_request_name_reply_in_queue;
62Lisp_Object QCdbus_request_name_reply_exists;
63Lisp_Object QCdbus_request_name_reply_already_owner;
64
54371585
MA
65/* Lisp symbols of D-Bus types. */
66Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
67Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
68Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
69Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
70Lisp_Object QCdbus_type_double, QCdbus_type_string;
71Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
da1fec2b
MA
72#ifdef DBUS_TYPE_UNIX_FD
73Lisp_Object QCdbus_type_unix_fd;
74#endif
54371585
MA
75Lisp_Object QCdbus_type_array, QCdbus_type_variant;
76Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
77
1dae9197
MA
78/* Whether we are reading a D-Bus event. */
79int xd_in_read_queued_messages = 0;
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))))
328 strcpy (x, SDATA (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);
509 XD_DEBUG_MESSAGE ("%c %u", dtype, (unsigned int) val);
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. */
534 char *val = SDATA (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 {
572 strcpy (signature, SDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
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
MA
791 if (STRINGP (bus))
792 connection = dbus_connection_open (SDATA (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
J
894 /* Unset session environment. */
895 if (data != NULL && data == (void*) XHASH (QCdbus_session_bus))
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
J
931 xd_toggle_watch,
932 (void*) XHASH (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
MA
938 /* We do not want to abort. */
939 putenv ("DBUS_FATAL_WARNINGS=0");
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) */)
5842a27b 1054 (int 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
MA
1065 int timeout = -1;
1066 int 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. */
5125905e
MA
1092 dmessage = dbus_message_new_method_call (SDATA (service),
1093 SDATA (path),
1094 SDATA (interface),
1095 SDATA (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]);
1119 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
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]);
1127 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
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) */)
5842a27b 1236 (int 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;
1246 int i = 6;
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. */
1275 dmessage = dbus_message_new_method_call (SDATA (service),
1276 SDATA (path),
1277 SDATA (interface),
1278 SDATA (method));
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]);
1301 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
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]);
1309 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
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) */)
5842a27b 1360 (int 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;
1368 int i;
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
603f0bf0 1380 XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) 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)))
1389 || (!dbus_message_set_destination (dmessage, SDATA (service))))
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]);
1408 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-2,
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]);
1416 XD_DEBUG_MESSAGE ("Parameter%d %s", i-2,
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) */)
5842a27b 1448 (int 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;
1456 int i;
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
603f0bf0 1468 XD_DEBUG_MESSAGE ("%lu %s ", (unsigned long) 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)))
1478 || (!dbus_message_set_destination (dmessage, SDATA (service))))
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]);
1497 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-2,
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]);
1505 XD_DEBUG_MESSAGE ("Parameter%d %s", i-2,
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) */)
5842a27b 1560 (int 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;
033b73e2 1568 int 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. */
5125905e
MA
1594 dmessage = dbus_message_new_signal (SDATA (path),
1595 SDATA (interface),
1596 SDATA (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]);
1612 XD_DEBUG_MESSAGE ("Parameter%d %s %s", i-4,
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]);
1620 XD_DEBUG_MESSAGE ("Parameter%d %s", i-4,
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)))
1748 || (strcmp (uname, SDATA (CAR_SAFE (key))) == 0))
1749 && ((path == NULL)
1750 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1751 || (strcmp (path,
1752 SDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
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 {
1827 if (data == (void*) XHASH (CAR_SAFE (busp)))
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) */)
1888 (int nargs, register Lisp_Object *args)
1889{
1890 Lisp_Object bus, service;
1891 struct gcpro gcpro1, gcpro2;
1892 DBusConnection *connection;
1893 unsigned int i;
1894 unsigned int value;
1895 unsigned int flags = 0;
1896 int result;
1897 DBusError derror;
1898
1899 bus = args[0];
1900 service = args[1];
1901
1902 /* Check parameters. */
1903 CHECK_STRING (service);
1904
1905 /* Process flags. */
1906 for (i = 2; i < nargs; ++i) {
1907 value = ((EQ (args[i], QCdbus_request_name_replace_existing))
1908 ? DBUS_NAME_FLAG_REPLACE_EXISTING
1909 : (EQ (args[i], QCdbus_request_name_allow_replacement))
1910 ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT
1911 : (EQ (args[i], QCdbus_request_name_do_not_queue))
1912 ? DBUS_NAME_FLAG_DO_NOT_QUEUE
1913 : -1);
1914 if (value == -1)
1915 XD_SIGNAL2 (build_string ("Unrecognized name request flag"), args[i]);
1916 flags |= value;
1917 }
1918
1919 /* Open a connection to the bus. */
1920 connection = xd_initialize (bus, TRUE);
1921
1922 /* Request the known name from the bus. */
1923 dbus_error_init (&derror);
1924 result = dbus_bus_request_name (connection, SDATA (service), flags,
1925 &derror);
1926 if (dbus_error_is_set (&derror))
1927 XD_ERROR (derror);
1928
1929 /* Cleanup. */
1930 dbus_error_free (&derror);
1931
1932 /* Return object. */
2bc92a93
MA
1933 switch (result)
1934 {
1935 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1936 return QCdbus_request_name_reply_primary_owner;
1937 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1938 return QCdbus_request_name_reply_in_queue;
1939 case DBUS_REQUEST_NAME_REPLY_EXISTS:
1940 return QCdbus_request_name_reply_exists;
1941 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1942 return QCdbus_request_name_reply_already_owner;
1943 default:
1944 /* This should not happen. */
1945 XD_SIGNAL2 (build_string ("Could not register service"), service);
1946 }
5b83ba18
MA
1947}
1948
033b73e2 1949DEFUN ("dbus-register-signal", Fdbus_register_signal, Sdbus_register_signal,
944cc4a8 1950 6, MANY, 0,
033b73e2
MA
1951 doc: /* Register for signal SIGNAL on the D-Bus BUS.
1952
0c372655
MA
1953BUS is either a Lisp symbol, `:system' or `:session', or a string
1954denoting the bus address.
033b73e2 1955
39abdd4a
MA
1956SERVICE is the D-Bus service name used by the sending D-Bus object.
1957It can be either a known name or the unique name of the D-Bus object
1958sending the signal. When SERVICE is nil, related signals from all
1959D-Bus objects shall be accepted.
033b73e2 1960
39abdd4a
MA
1961PATH is the D-Bus object path SERVICE is registered. It can also be
1962nil if the path name of incoming signals shall not be checked.
033b73e2 1963
39abdd4a
MA
1964INTERFACE is an interface offered by SERVICE. It must provide SIGNAL.
1965HANDLER is a Lisp function to be called when the signal is received.
944cc4a8
MA
1966It must accept as arguments the values SIGNAL is sending.
1967
1968All other arguments ARGS, if specified, must be strings. They stand
1969for the respective arguments of the signal in their order, and are
1970used for filtering as well. A nil argument might be used to preserve
1971the order.
1972
1973INTERFACE, SIGNAL and HANDLER must not be nil. Example:
033b73e2
MA
1974
1975\(defun my-signal-handler (device)
1976 (message "Device %s added" device))
1977
1978\(dbus-register-signal
52da95fa
MA
1979 :system "org.freedesktop.Hal" "/org/freedesktop/Hal/Manager"
1980 "org.freedesktop.Hal.Manager" "DeviceAdded" 'my-signal-handler)
033b73e2 1981
f5306ca3
MA
1982 => ((:system "org.freedesktop.Hal.Manager" "DeviceAdded")
1983 ("org.freedesktop.Hal" "/org/freedesktop/Hal/Manager" my-signal-handler))
033b73e2
MA
1984
1985`dbus-register-signal' returns an object, which can be used in
944cc4a8
MA
1986`dbus-unregister-object' for removing the registration.
1987
1988usage: (dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest ARGS) */)
5842a27b 1989 (int nargs, register Lisp_Object *args)
033b73e2 1990{
944cc4a8
MA
1991 Lisp_Object bus, service, path, interface, signal, handler;
1992 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
17bc8f94 1993 Lisp_Object uname, key, key1, value;
033b73e2 1994 DBusConnection *connection;
944cc4a8 1995 int i;
52da95fa 1996 char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
c0894fb9 1997 char x[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
39abdd4a 1998 DBusError derror;
033b73e2
MA
1999
2000 /* Check parameters. */
944cc4a8
MA
2001 bus = args[0];
2002 service = args[1];
2003 path = args[2];
2004 interface = args[3];
2005 signal = args[4];
2006 handler = args[5];
2007
39abdd4a
MA
2008 if (!NILP (service)) CHECK_STRING (service);
2009 if (!NILP (path)) CHECK_STRING (path);
033b73e2 2010 CHECK_STRING (interface);
52da95fa 2011 CHECK_STRING (signal);
17bc8f94
MA
2012 if (!FUNCTIONP (handler))
2013 wrong_type_argument (intern ("functionp"), handler);
944cc4a8 2014 GCPRO6 (bus, service, path, interface, signal, handler);
033b73e2 2015
52da95fa
MA
2016 /* Retrieve unique name of service. If service is a known name, we
2017 will register for the corresponding unique name, if any. Signals
2018 are sent always with the unique name as sender. Note: the unique
2019 name of "org.freedesktop.DBus" is that string itself. */
5125905e
MA
2020 if ((STRINGP (service))
2021 && (SBYTES (service) > 0)
eb7c7bf5
MA
2022 && (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0)
2023 && (strncmp (SDATA (service), ":", 1) != 0))
f5306ca3
MA
2024 {
2025 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
2026 /* When there is no unique name, we mark it with an empty
2027 string. */
2028 if (NILP (uname))
fff4e459 2029 uname = empty_unibyte_string;
f5306ca3 2030 }
52da95fa 2031 else
f5306ca3 2032 uname = service;
52da95fa 2033
f5306ca3
MA
2034 /* Create a matching rule if the unique name exists (when no
2035 wildcard). */
5125905e 2036 if (NILP (uname) || (SBYTES (uname) > 0))
f5306ca3
MA
2037 {
2038 /* Open a connection to the bus. */
2536a4b7 2039 connection = xd_initialize (bus, TRUE);
033b73e2 2040
f5306ca3
MA
2041 /* Create a rule to receive related signals. */
2042 sprintf (rule,
2043 "type='signal',interface='%s',member='%s'",
2044 SDATA (interface),
2045 SDATA (signal));
033b73e2 2046
f5306ca3
MA
2047 /* Add unique name and path to the rule if they are non-nil. */
2048 if (!NILP (uname))
c0894fb9
MA
2049 {
2050 sprintf (x, ",sender='%s'", SDATA (uname));
2051 strcat (rule, x);
2052 }
39abdd4a 2053
f5306ca3 2054 if (!NILP (path))
c0894fb9
MA
2055 {
2056 sprintf (x, ",path='%s'", SDATA (path));
2057 strcat (rule, x);
2058 }
39abdd4a 2059
944cc4a8
MA
2060 /* Add arguments to the rule if they are non-nil. */
2061 for (i = 6; i < nargs; ++i)
2062 if (!NILP (args[i]))
2063 {
2064 CHECK_STRING (args[i]);
c0894fb9
MA
2065 sprintf (x, ",arg%d='%s'", i-6, SDATA (args[i]));
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;
17bc8f94 2125 DBusError derror;
5b83ba18 2126 Lisp_Object args[2] = { bus, service };
17bc8f94 2127
17bc8f94 2128 /* Check parameters. */
17bc8f94
MA
2129 CHECK_STRING (service);
2130 CHECK_STRING (path);
2131 CHECK_STRING (interface);
2132 CHECK_STRING (method);
2133 if (!FUNCTIONP (handler))
2134 wrong_type_argument (intern ("functionp"), handler);
2135 /* TODO: We must check for a valid service name, otherwise there is
2136 a segmentation fault. */
2137
5b83ba18 2138 /* Request the name. */
2bc92a93 2139 if (NILP (dont_register_service))
5b83ba18 2140 Fdbus_register_service (2, args);
17bc8f94 2141
f04bb9b2
MA
2142 /* Create a hash table entry. We use nil for the unique name,
2143 because the method might be called from anybody. */
17bc8f94
MA
2144 key = list3 (bus, interface, method);
2145 key1 = list4 (Qnil, service, path, handler);
f04bb9b2 2146 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
a31d47c7 2147
17bc8f94 2148 if (NILP (Fmember (key1, value)))
f04bb9b2 2149 Fputhash (key, Fcons (key1, value), Vdbus_registered_objects_table);
033b73e2 2150
f5306ca3
MA
2151 /* Return object. */
2152 return list2 (key, list3 (service, path, handler));
033b73e2
MA
2153}
2154
033b73e2
MA
2155\f
2156void
971de7fb 2157syms_of_dbusbind (void)
033b73e2
MA
2158{
2159
d67b4f80 2160 Qdbus_init_bus = intern_c_string ("dbus-init-bus");
058ed861
MA
2161 staticpro (&Qdbus_init_bus);
2162 defsubr (&Sdbus_init_bus);
2163
0c372655
MA
2164 Qdbus_close_bus = intern_c_string ("dbus-close-bus");
2165 staticpro (&Qdbus_close_bus);
2166 defsubr (&Sdbus_close_bus);
2167
d67b4f80 2168 Qdbus_get_unique_name = intern_c_string ("dbus-get-unique-name");
033b73e2
MA
2169 staticpro (&Qdbus_get_unique_name);
2170 defsubr (&Sdbus_get_unique_name);
2171
d67b4f80 2172 Qdbus_call_method = intern_c_string ("dbus-call-method");
033b73e2
MA
2173 staticpro (&Qdbus_call_method);
2174 defsubr (&Sdbus_call_method);
2175
d67b4f80 2176 Qdbus_call_method_asynchronously = intern_c_string ("dbus-call-method-asynchronously");
13ecc6dc
MA
2177 staticpro (&Qdbus_call_method_asynchronously);
2178 defsubr (&Sdbus_call_method_asynchronously);
2179
d67b4f80 2180 Qdbus_method_return_internal = intern_c_string ("dbus-method-return-internal");
8c7a4ac5
MA
2181 staticpro (&Qdbus_method_return_internal);
2182 defsubr (&Sdbus_method_return_internal);
abe136ee 2183
d67b4f80 2184 Qdbus_method_error_internal = intern_c_string ("dbus-method-error-internal");
13ecc6dc
MA
2185 staticpro (&Qdbus_method_error_internal);
2186 defsubr (&Sdbus_method_error_internal);
2187
d67b4f80 2188 Qdbus_send_signal = intern_c_string ("dbus-send-signal");
033b73e2
MA
2189 staticpro (&Qdbus_send_signal);
2190 defsubr (&Sdbus_send_signal);
2191
5b83ba18
MA
2192 Qdbus_register_service = intern_c_string ("dbus-register-service");
2193 staticpro (&Qdbus_register_service);
2194 defsubr (&Sdbus_register_service);
2195
d67b4f80 2196 Qdbus_register_signal = intern_c_string ("dbus-register-signal");
033b73e2
MA
2197 staticpro (&Qdbus_register_signal);
2198 defsubr (&Sdbus_register_signal);
2199
d67b4f80 2200 Qdbus_register_method = intern_c_string ("dbus-register-method");
17bc8f94
MA
2201 staticpro (&Qdbus_register_method);
2202 defsubr (&Sdbus_register_method);
2203
d67b4f80 2204 Qdbus_error = intern_c_string ("dbus-error");
033b73e2
MA
2205 staticpro (&Qdbus_error);
2206 Fput (Qdbus_error, Qerror_conditions,
2207 list2 (Qdbus_error, Qerror));
2208 Fput (Qdbus_error, Qerror_message,
d67b4f80 2209 make_pure_c_string ("D-Bus error"));
033b73e2 2210
d67b4f80 2211 QCdbus_system_bus = intern_c_string (":system");
39abdd4a
MA
2212 staticpro (&QCdbus_system_bus);
2213
d67b4f80 2214 QCdbus_session_bus = intern_c_string (":session");
39abdd4a 2215 staticpro (&QCdbus_session_bus);
033b73e2 2216
5b83ba18
MA
2217 QCdbus_request_name_allow_replacement = intern_c_string (":allow-replacement");
2218 staticpro (&QCdbus_request_name_allow_replacement);
2219
2220 QCdbus_request_name_replace_existing = intern_c_string (":replace-existing");
2221 staticpro (&QCdbus_request_name_replace_existing);
2222
2223 QCdbus_request_name_do_not_queue = intern_c_string (":do-not-queue");
2224 staticpro (&QCdbus_request_name_do_not_queue);
2225
2226 QCdbus_request_name_reply_primary_owner = intern_c_string (":primary-owner");
2227 staticpro (&QCdbus_request_name_reply_primary_owner);
2228
2229 QCdbus_request_name_reply_exists = intern_c_string (":exists");
2230 staticpro (&QCdbus_request_name_reply_exists);
2231
2232 QCdbus_request_name_reply_in_queue = intern_c_string (":in-queue");
2233 staticpro (&QCdbus_request_name_reply_in_queue);
2234
2235 QCdbus_request_name_reply_already_owner = intern_c_string (":already-owner");
2236 staticpro (&QCdbus_request_name_reply_already_owner);
2237
d67b4f80 2238 QCdbus_timeout = intern_c_string (":timeout");
90b3fc84
MA
2239 staticpro (&QCdbus_timeout);
2240
d67b4f80 2241 QCdbus_type_byte = intern_c_string (":byte");
54371585
MA
2242 staticpro (&QCdbus_type_byte);
2243
d67b4f80 2244 QCdbus_type_boolean = intern_c_string (":boolean");
54371585
MA
2245 staticpro (&QCdbus_type_boolean);
2246
d67b4f80 2247 QCdbus_type_int16 = intern_c_string (":int16");
54371585
MA
2248 staticpro (&QCdbus_type_int16);
2249
d67b4f80 2250 QCdbus_type_uint16 = intern_c_string (":uint16");
54371585
MA
2251 staticpro (&QCdbus_type_uint16);
2252
d67b4f80 2253 QCdbus_type_int32 = intern_c_string (":int32");
54371585
MA
2254 staticpro (&QCdbus_type_int32);
2255
d67b4f80 2256 QCdbus_type_uint32 = intern_c_string (":uint32");
54371585
MA
2257 staticpro (&QCdbus_type_uint32);
2258
d67b4f80 2259 QCdbus_type_int64 = intern_c_string (":int64");
54371585
MA
2260 staticpro (&QCdbus_type_int64);
2261
d67b4f80 2262 QCdbus_type_uint64 = intern_c_string (":uint64");
54371585
MA
2263 staticpro (&QCdbus_type_uint64);
2264
d67b4f80 2265 QCdbus_type_double = intern_c_string (":double");
54371585
MA
2266 staticpro (&QCdbus_type_double);
2267
d67b4f80 2268 QCdbus_type_string = intern_c_string (":string");
54371585
MA
2269 staticpro (&QCdbus_type_string);
2270
d67b4f80 2271 QCdbus_type_object_path = intern_c_string (":object-path");
54371585
MA
2272 staticpro (&QCdbus_type_object_path);
2273
d67b4f80 2274 QCdbus_type_signature = intern_c_string (":signature");
54371585
MA
2275 staticpro (&QCdbus_type_signature);
2276
da1fec2b
MA
2277#ifdef DBUS_TYPE_UNIX_FD
2278 QCdbus_type_unix_fd = intern_c_string (":unix-fd");
2279 staticpro (&QCdbus_type_unix_fd);
2280#endif
2281
d67b4f80 2282 QCdbus_type_array = intern_c_string (":array");
54371585
MA
2283 staticpro (&QCdbus_type_array);
2284
d67b4f80 2285 QCdbus_type_variant = intern_c_string (":variant");
54371585
MA
2286 staticpro (&QCdbus_type_variant);
2287
d67b4f80 2288 QCdbus_type_struct = intern_c_string (":struct");
54371585
MA
2289 staticpro (&QCdbus_type_struct);
2290
d67b4f80 2291 QCdbus_type_dict_entry = intern_c_string (":dict-entry");
54371585
MA
2292 staticpro (&QCdbus_type_dict_entry);
2293
0c372655 2294 DEFVAR_LISP ("dbus-registered-buses",
29208e82 2295 Vdbus_registered_buses,
0c372655
MA
2296 doc: /* List of D-Bus buses we are polling for messages. */);
2297 Vdbus_registered_buses = Qnil;
2298
f04bb9b2 2299 DEFVAR_LISP ("dbus-registered-objects-table",
29208e82 2300 Vdbus_registered_objects_table,
39abdd4a 2301 doc: /* Hash table of registered functions for D-Bus.
0c372655 2302
f04bb9b2
MA
2303There are two different uses of the hash table: for accessing
2304registered interfaces properties, targeted by signals or method calls,
2305and for calling handlers in case of non-blocking method call returns.
13ecc6dc
MA
2306
2307In the first case, the key in the hash table is the list (BUS
0c372655
MA
2308INTERFACE MEMBER). BUS is either a Lisp symbol, `:system' or
2309`:session', or a string denoting the bus address. INTERFACE is a
2310string which denotes a D-Bus interface, and MEMBER, also a string, is
2311either a method, a signal or a property INTERFACE is offering. All
2312arguments but BUS must not be nil.
a31d47c7 2313
f5306ca3 2314The value in the hash table is a list of quadruple lists
f04bb9b2 2315\((UNAME SERVICE PATH OBJECT) (UNAME SERVICE PATH OBJECT) ...).
a31d47c7 2316SERVICE is the service name as registered, UNAME is the corresponding
f04bb9b2
MA
2317unique name. In case of registered methods and properties, UNAME is
2318nil. PATH is the object path of the sending object. All of them can
2319be nil, which means a wildcard then. OBJECT is either the handler to
2320be called when a D-Bus message, which matches the key criteria,
2321arrives (methods and signals), or a cons cell containing the value of
2322the property.
13ecc6dc 2323
0c372655
MA
2324In the second case, the key in the hash table is the list (BUS
2325SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
2326string denoting the bus address. SERIAL is the serial number of the
2327non-blocking method call, a reply is expected. Both arguments must
2328not be nil. The value in the hash table is HANDLER, the function to
2329be called when the D-Bus reply message arrives. */);
2330 {
2331 Lisp_Object args[2];
2332 args[0] = QCtest;
2333 args[1] = Qequal;
2334 Vdbus_registered_objects_table = Fmake_hash_table (2, args);
2335 }
033b73e2 2336
29208e82 2337 DEFVAR_LISP ("dbus-debug", Vdbus_debug,
39abdd4a 2338 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
2339#ifdef DBUS_DEBUG
2340 Vdbus_debug = Qt;
a79b0f28
MA
2341 /* We can also set environment variable DBUS_VERBOSE=1 in order to
2342 see more traces. This requires libdbus-1 to be configured with
2343 --enable-verbose-mode. */
033b73e2
MA
2344#else
2345 Vdbus_debug = Qnil;
2346#endif
2347
d67b4f80 2348 Fprovide (intern_c_string ("dbusbind"), Qnil);
033b73e2
MA
2349
2350}
2351
2352#endif /* HAVE_DBUS */
79f10da0 2353