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